Brought over some code from the full refactor branch

This commit is contained in:
2026-01-26 12:32:41 -05:00
parent 5a67a416bf
commit e04d167dab
53 changed files with 1101 additions and 742 deletions
+5 -5
View File
@@ -19,6 +19,10 @@
</properties>
<repositories>
<repository>
<id>maven-central</id>
<url>https://nexus.funkemunky.cc/repository/maven-central/</url>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
@@ -27,10 +31,6 @@
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>evokegames</id>
<url>https://maven.evokegames.gg/snapshots</url>
</repository>
<repository>
<id>aikar</id>
<url>https://repo.aikar.co/content/groups/aikar/</url>
@@ -267,7 +267,7 @@
<dependency>
<groupId>com.github.retrooper</groupId>
<artifactId>packetevents-spigot</artifactId>
<version>2.9.4</version>
<version>2.11.1</version>
<scope>compile</scope>
</dependency>
<dependency>
@@ -17,6 +17,8 @@ import dev.brighten.ac.handler.PacketHandler;
import dev.brighten.ac.handler.entity.FakeEntityTracker;
import dev.brighten.ac.handler.keepalive.KeepaliveProcessor;
import dev.brighten.ac.handler.keepalive.actions.ActionManager;
import dev.brighten.ac.handler.protocol.Protocol;
import dev.brighten.ac.handler.protocol.impl.NoAPI;
import dev.brighten.ac.logging.LoggerManager;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.annotation.ConfigSetting;
@@ -30,6 +32,7 @@ import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.WorldInfo;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.PackagePrivate;
import org.bukkit.Bukkit;
import org.bukkit.World;
@@ -116,6 +119,9 @@ public class Anticheat extends JavaPlugin {
private final RollingAverageDouble tps = new RollingAverageDouble(4, 20);
private final Map<UUID, WorldInfo> worldInfoMap = new HashMap<>();
@Setter
private Protocol protocol = new NoAPI();
private final List<BaseCommand> commands = new ArrayList<>();
public static boolean allowDebug = true;
@@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.Anticheat;
@@ -19,7 +20,6 @@ import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.EntityData;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
@@ -46,7 +46,7 @@ public class Hitbox extends Check {
if(packet.getAction() != WrapperPlayClientInteractEntity.InteractAction.ATTACK)
return;
Optional<TrackedEntity> entity = player.getEntityLocationHandler().getTrackedEntity(packet.getEntityId());
Optional<TrackedEntity> entity = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(packet.getEntityId());
if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
attacks.add(new Tuple<>(entity.get(),
@@ -118,7 +118,7 @@ public class Hitbox extends Check {
boolean didSneakOrElytra = player.getInfo().getLastSneak().isNotPassed(40)
|| player.getInfo().getLastElytra().isNotPassed(40);
List<Vector> directions = new ArrayList<>(Arrays.asList(MathUtils.getDirection(
List<Vector3d> directions = new ArrayList<>(Arrays.asList(MathUtils.getDirection(
player.getMovement().getTo().getLoc().getYaw(),
player.getMovement().getTo().getLoc().getPitch()),
MathUtils.getDirection(player.getMovement().getFrom().getLoc().getYaw(),
@@ -126,7 +126,7 @@ public class Hitbox extends Check {
if(!didSneakOrElytra) {
to.add(0, 1.62f, 0);
for (Vector direction : directions) {
for (Vector3d direction : directions) {
for (SimpleCollisionBox targetBox : boxes) {
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox);
@@ -143,7 +143,7 @@ public class Hitbox extends Check {
}
//Checking all possible eyeheights since client actions notoriously desync from the server side
} else {
for (Vector direction : directions) {
for (Vector3d direction : directions) {
for (double eyeHeight : player.getMovement().getEyeHeights()) {
for (SimpleCollisionBox targetBox : boxes) {
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox);
@@ -180,7 +180,7 @@ public class Hitbox extends Check {
debug("buffer: %.3f distance=%.2f hits=%s sneaking=%s", buffer, distance, hits,
player.getInfo().isSneaking());
} else if(player.getEntityLocationHandler().streak > 1) {
} else if(player.getEntityTrackHandler().streak > 1) {
if (++hbuffer > 5) {
flag("%.1f;%.1f;%.1f", entity.getNewEntityLocation().x, entity.getNewEntityLocation().y, entity.getNewEntityLocation().z);
}
@@ -1,6 +1,5 @@
package dev.brighten.ac.check.impl.combat.killaura;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientAnimation;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import dev.brighten.ac.api.check.CheckType;
@@ -29,10 +28,10 @@ public class KABot extends Check {
@Bind
WAction<WrapperPlayClientInteractEntity> packet = packet -> {
val optional = player.getEntityLocationHandler().getTrackedEntity(packet.getEntityId());
val optional = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(packet.getEntityId());
if(optional.isPresent()
&& (player.getEntityLocationHandler().clientHasEntity.get()
&& (player.getEntityTrackHandler().clientHasEntity.get()
|| !optional.get().getFakeMobs().isEmpty())) {
if(++buffer > 3) {
flag("Attacked player without attacking bot!");
@@ -1,6 +1,6 @@
package dev.brighten.ac.check.impl.combat.killaura;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
@@ -13,7 +13,6 @@ 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
@@ -43,14 +42,13 @@ public class KATrace extends Check {
return;
}
var trackedEntity = player.getEntityLocationHandler().getTrackedEntity(player.getInfo().getTarget().getEntityId());
var trackedEntity = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(player.getInfo().getTarget().getEntityId());
if(trackedEntity.isEmpty()) {
return;
}
// Getting the target's bounding box
SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget()
.getLocation(), trackedEntity.get());
SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget().getLocation(), trackedEntity.get());
if(targetBox == null) return;
@@ -59,12 +57,12 @@ public class KATrace extends Check {
// Setting the player's eye height based on their sneak status
origin.add(0, player.getEyeHeight(), 0);
final Vector originVec = origin.toVector();
final Vector3d originVec = origin.toVector();
// Setting a trace based on their view direction
RayCollision collision = new RayCollision(originVec, origin.getDirection());
Vector targetPoint = collision.collisionPoint(targetBox);
Vector3d 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;
@@ -84,7 +82,7 @@ public class KATrace extends Check {
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));
Vector3d point = collision.collisionPoint(box.copy().shrink(0.005f, 0.005f, 0.005f));
if (point != null && originVec.distanceSquared(point) < dist - 0.2) {
rayCollidedOnBlock = true;
@@ -31,7 +31,7 @@ public class KACalc extends KListener {
@Bind
WAction<WrapperPlayClientPlayerFlying> flying = packet -> {
if(player.getInfo().getTarget() == null || player.getInfo().lastAttack.isPassed(40)) return;
Optional<TrackedEntity> optional = player.getEntityLocationHandler()
Optional<TrackedEntity> optional = player.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(player.getInfo().getTarget().getEntityId());
if(optional.isEmpty()) return;
@@ -46,7 +46,7 @@ public class KACalc extends KListener {
KLocation originKLoc = player.getMovement().getTo().getLoc().clone()
.add(0, player.getInfo().isSneaking() ? 1.54f : 1.62f, 0);
double halfHeight = player.getInfo().getTarget().getEyeHeight() / 2;
double halfHeight = player.getInfo().getTarget().getPose().eyeHeight / 2;
KLocation targetLocation = new KLocation(current.getX(), current.getY(), current.getZ());
var rotations = MathUtils
.getRotation(originKLoc, targetLocation.clone().add(0, halfHeight, 0));
@@ -1,6 +1,7 @@
package dev.brighten.ac.check.impl.movement;
import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerPositionAndLook;
import dev.brighten.ac.Anticheat;
@@ -18,7 +19,6 @@ import dev.brighten.ac.utils.annotation.Bind;
import dev.brighten.ac.utils.objects.evicting.EvictingSet;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location;
import org.bukkit.util.Vector;
import java.util.List;
import java.util.Set;
@@ -31,7 +31,7 @@ public class Phase extends Check {
}
private int ticks;
private final Set<Vector> POSITIONS = new EvictingSet<>(10);
private final Set<Vector3d> POSITIONS = new EvictingSet<>(10);
private Location teleportLoc = null;
@Bind
@@ -1,6 +1,7 @@
package dev.brighten.ac.check.impl.movement.speed;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
@@ -36,11 +37,11 @@ public class Speed extends Check {
moveFactor+= (float) (moveFactor * 0.30000001192092896D);
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SPEED))
if(player.getPotionHandler().hasPotionEffect(PotionTypes.SPEED))
moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SPEED)
* (0.200000000298023224D)) * moveFactor);
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW))
if(player.getPotionHandler().hasPotionEffect(PotionTypes.SLOWNESS))
moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SLOW)
* (-0.15000000596046448D)) * moveFactor);
@@ -1,6 +1,8 @@
package dev.brighten.ac.check.impl.movement.velocity;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check;
@@ -12,12 +14,10 @@ import dev.brighten.ac.utils.BlockUtils;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.annotation.Bind;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import lombok.val;
import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList;
import java.util.List;
@@ -61,8 +61,8 @@ public class VelocityB extends Check {
val underBlockLoc = previousFrom != null
? player.getMovement().getFrom().getLoc() : player.getMovement().getTo().getLoc();
WrappedBlock underMaterial = player.getBlockUpdateHandler()
.getBlock(new IntVector(MathHelper.floor_double(underBlockLoc.getX()),
WrappedBlock underMaterial = player.getWorldTracker()
.getBlock(new Vector3i(MathHelper.floor_double(underBlockLoc.getX()),
MathHelper.floor_double(underBlockLoc.getY() - 1),
MathHelper.floor_double(underBlockLoc.getZ())));
@@ -87,8 +87,8 @@ public class VelocityB extends Check {
double pmotionx = 0, pmotionz = 0;
boolean onGround = player.getMovement().getFrom().isOnGround();
val speed = player.getPotionHandler().getEffectByType(PotionEffectType.SPEED);
val slow = player.getPotionHandler().getEffectByType(PotionEffectType.SLOW);
val speed = player.getPotionHandler().getEffectByType(PotionTypes.SPEED);
val slow = player.getPotionHandler().getEffectByType(PotionTypes.SLOWNESS);
for (Iteration iteration : iterations) {
float forward = iteration.f, strafe = iteration.s;
@@ -138,9 +138,9 @@ public class VelocityB extends Check {
aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
if (speed.isPresent())
aiMoveSpeed += (speed.get().getAmplifier() + 1) * 0.20000000298023224D * aiMoveSpeed;
aiMoveSpeed += (speed.get().properties().amplifier() + 1) * 0.20000000298023224D * aiMoveSpeed;
if (slow.isPresent())
aiMoveSpeed += (slow.get().getAmplifier() + 1) * -0.15000000596046448D * aiMoveSpeed;
aiMoveSpeed += (slow.get().properties().amplifier() + 1) * -0.15000000596046448D * aiMoveSpeed;
float f5;
if (onGround) {
@@ -1,6 +1,7 @@
package dev.brighten.ac.check.impl.world;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.api.check.CheckType;
@@ -35,7 +36,7 @@ public class BlockA extends Check {
WAction<WrapperPlayClientPlayerBlockPlacement> blockPlace = packet -> {
Vector3d loc = packet.getBlockPosition().toVector3d();
WrappedBlock block = player.getBlockUpdateHandler().getBlock(loc);
WrappedBlock block = player.getWorldTracker().getBlock(new Vector3i(MathUtils.floor(loc.getX()), MathUtils.floor(loc.getY()), MathUtils.floor(loc.getZ())));
CollisionBox box = BlockData.getData(block.getType()).getBox(player, block, player.getPlayerVersion());
@@ -14,12 +14,12 @@ import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.annotation.Bind;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.BlockData;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
@CheckData(name = "Block (D)", checkId = "blockc", type = CheckType.INTERACT)
public class BlockD extends Check {
@@ -45,7 +45,7 @@ public class BlockD extends Check {
packet.getFace().getModY(),
packet.getFace().getModZ());
WrappedBlock block = new WrappedBlock(new IntVector(packet.getBlockPosition()),
WrappedBlock block = new WrappedBlock(packet.getBlockPosition(),
placedType,
WrappedBlockState.getDefaultState(placedType));
blockPlaceLocations.put(blockpos, block);
@@ -22,17 +22,19 @@ import dev.brighten.ac.data.info.GeneralInformation;
import dev.brighten.ac.data.info.LagInformation;
import dev.brighten.ac.data.obj.InstantAction;
import dev.brighten.ac.data.obj.NormalAction;
import dev.brighten.ac.handler.EntityLocationHandler;
import dev.brighten.ac.handler.EntityTrackHandler;
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.protocol.Protocol;
import dev.brighten.ac.messages.Messages;
import dev.brighten.ac.packet.TransactionServerWrapper;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.Helper;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.objects.evicting.EvictingList;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
@@ -49,7 +51,6 @@ import me.hydro.emulator.object.input.DataSupplier;
import me.hydro.emulator.util.mcp.AxisAlignedBB;
import me.hydro.emulator.util.mcp.BlockPos;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -72,10 +73,10 @@ public class APlayer {
private VelocityHandler velocityHandler;
@Getter
private EntityLocationHandler entityLocationHandler;
private EntityTrackHandler entityTrackHandler;
@Getter
private BlockUpdateHandler blockUpdateHandler;
private BlockUpdateHandler worldTracker;
@Getter
private CheckHandler checkHandler;
@@ -138,8 +139,8 @@ public class APlayer {
this.movement = new MovementHandler(this);
this.potionHandler = new PotionHandler(this);
this.velocityHandler = new VelocityHandler(this);
this.entityLocationHandler = new EntityLocationHandler(this);
this.blockUpdateHandler = new BlockUpdateHandler(this);
this.entityTrackHandler = new EntityTrackHandler(this);
this.worldTracker = new BlockUpdateHandler(this);
this.checkHandler = new CheckHandler(this);
this.info = new GeneralInformation();
this.lagInfo = new LagInformation();
@@ -151,7 +152,7 @@ public class APlayer {
// Grabbing the protocol version of the player.
Anticheat.INSTANCE.getLogger().info("Attempting Getting player version for " + getBukkitPlayer().getName());
ClientVersion version = ClientVersion.getById(Protocol.getProtocol().getPlayerVersion(getBukkitPlayer()));
ClientVersion version = ClientVersion.getById(Anticheat.INSTANCE.getProtocol().getPlayerVersion(this));
this.playerVersion = version;
@@ -187,7 +188,7 @@ public class APlayer {
@Override
public Block getBlockAt(BlockPos blockPos) {
//Optional<org.bukkit.block.Block>
var block = APlayer.this.getBlockUpdateHandler()
var block = APlayer.this.getWorldTracker()
.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ());
StateType type = block.getType();
@@ -228,7 +229,7 @@ public class APlayer {
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1));
Vector loc1 = coll.collisionPoint(2);
Vector3d loc1 = coll.collisionPoint(2);
List<EntityData<?>> dataList = new ArrayList<>();
@@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.entity.TrackedEntity;
@@ -132,11 +133,11 @@ public class BlockInformation {
}
final StateType type =
player.getBlockUpdateHandler().getBlock(new IntVector(x, y, z)).getType();
player.getWorldTracker().getBlock(new Vector3i(x, y, z)).getType();
if (type != StateTypes.AIR) {
IntVector vec = new IntVector(x, y, z);
Vector3i vec = new Vector3i(x, y, z);
CollisionBox blockBox = BlockData.getData(type)
.getBox(player, vec, player.getPlayerVersion());
@@ -1,10 +1,12 @@
package dev.brighten.ac.data.info;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.data.obj.Pose;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.packet.PlayerCapabilities;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.KPotionEffect;
import dev.brighten.ac.utils.PastLocation;
import dev.brighten.ac.utils.math.RollingAverage;
import dev.brighten.ac.utils.objects.evicting.EvictingList;
@@ -12,8 +14,6 @@ import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.entity.LivingEntity;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList;
import java.util.Collections;
@@ -33,8 +33,8 @@ public class GeneralInformation {
lastBlockUpdate = new TickTimer(), lastMiscNear = new TickTimer(), lastHalfBlock = new TickTimer(),
lastFence = new TickTimer(), lastFakeBotHit = new TickTimer(), lastInventoryOpen = new TickTimer(),
botAttack = new TickTimer(), lastAttack = new TickTimer(), lastCanceledFlying = new TickTimer();
public LivingEntity target;
public Optional<PotionEffect> groundJumpBoost;
public TrackedEntity target;
public Optional<KPotionEffect> groundJumpBoost;
public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative,
sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock,
inventoryOpen, swimming;
@@ -46,4 +46,7 @@ public class GeneralInformation {
public List<Vector3d> velocityHistory = Collections.synchronizedList(new EvictingList<>(5));
public List<PlayerCapabilities> possibleCapabilities = new ArrayList<>();
private int clientGroundTicks, clientAirTicks;
private double walkSpeed, flySpeed;
private PlayerInput playerInput;
private Pose pose;
}
@@ -0,0 +1,14 @@
package dev.brighten.ac.data.info;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerInput;
public record PlayerInput(boolean forward, boolean backward, boolean left, boolean right, boolean jump, boolean sprint, boolean shift) {
public static PlayerInput getFromPacket(WrapperPlayClientPlayerInput packet) {
return new PlayerInput(packet.isForward(), packet.isBackward(), packet.isLeft(),
packet.isRight(), packet.isJump(), packet.isSprint(), packet.isShift());
}
public static final PlayerInput NONE = new PlayerInput(false, false, false,
false, false, false, false);
}
@@ -1,10 +1,10 @@
package dev.brighten.ac.data.obj;
import dev.brighten.ac.handler.block.World;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.World;
@Getter
@Setter
@@ -0,0 +1,25 @@
package dev.brighten.ac.data.obj;
public enum Pose {
STANDING(0.6f, 1.8f, 1.62f),
FALL_FLYING(0.6f, 0.6f, 0.4f),
SLEEPING(0.2f, 0.2f, 0.2f),
SWIMMING(0.6f, 0.6f, 0.4f),
SPIN_ATTACK(0.6f, 0.6f, 0.4f),
CROUCHING(0.6f, 1.5f, 1.27f),
DYING(0.2f, 0.2f, 0.2f),
// Non-player poses
NINE_CROUCHING(0.6f, 1.65f, 1.54f), // 1.9-1.13 clients have a slightly different crouching hitbox
LONG_JUMPING(0.6f, 1.8f, 1.54f); // DUMMY (players can't have this pose)
public final float width;
public final float height;
public final float eyeHeight;
Pose(float width, float height, float eyeHeight) {
this.width = width;
this.height = height;
this.eyeHeight = eyeHeight;
}
}
@@ -1,13 +1,13 @@
package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.Materials;
import dev.brighten.ac.utils.annotation.Init;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.EntityData;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
@@ -31,7 +31,7 @@ import java.util.stream.Collectors;
@Init
public class BBRevealHandler implements Listener {
private final Map<UUID, Set<IntVector>> blocksToShow = new HashMap<>();
private final Map<UUID, Set<Vector3i>> blocksToShow = new HashMap<>();
private final Set<Entity> entitiesToShow = new HashSet<>();
public static BBRevealHandler INSTANCE;
@@ -52,9 +52,9 @@ public class BBRevealHandler implements Listener {
if(player == null || !player.getWrappedPlayer().getItemInHand().isSimilar(wand)) return;
if(event.getAction() == Action.RIGHT_CLICK_BLOCK) {
IntVector blockLoc = new IntVector(event.getClickedBlock().getX(),
Vector3i blockLoc = new Vector3i(event.getClickedBlock().getX(),
event.getClickedBlock().getY(), event.getClickedBlock().getZ());
Set<IntVector> blocksToShow = this.blocksToShow
Set<Vector3i> blocksToShow = this.blocksToShow
.computeIfAbsent(event.getPlayer().getUniqueId(), k -> new HashSet<>());
if(blocksToShow.contains(blockLoc)) {
blocksToShow.remove(blockLoc);
@@ -63,7 +63,7 @@ public class BBRevealHandler implements Listener {
.create());
} else {
blocksToShow.add(blockLoc);
WrappedBlock block = player.getBlockUpdateHandler().getBlock(blockLoc);
WrappedBlock block = player.getWorldTracker().getCurrentWorld().get().getBlock(blockLoc);
event.getPlayer().spigot().sendMessage(new ComponentBuilder("Now showing block: ")
.color(ChatColor.GREEN).color(ChatColor.WHITE).append(event.getClickedBlock().getType().name())
.color(ChatColor.GRAY)
@@ -107,7 +107,7 @@ public class BBRevealHandler implements Listener {
if(player.isEmpty()) return;
blocks.forEach(blockLoc -> {
var block = player.get().getBlockUpdateHandler().getBlock(blockLoc);
var block = player.get().getWorldTracker().getCurrentWorld().get().getBlock(blockLoc);
var blockBox = BlockData.getData(block.getType())
.getBox(player.get(), blockLoc, player.get().getPlayerVersion());
@@ -1,14 +1,17 @@
package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.protocol.attribute.Attribute;
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityPositionSync;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport;
import dev.brighten.ac.Anticheat;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.entity.FakeMob;
import dev.brighten.ac.handler.entity.TrackedEntity;
@@ -18,20 +21,15 @@ import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
import dev.brighten.ac.utils.world.types.RayCollision;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@RequiredArgsConstructor
public class EntityLocationHandler {
public class EntityTrackHandler {
private final APlayer data;
@Getter
private Map<Integer, TrackedEntity> trackedEntities = new Int2ObjectArrayMap<>();
private final Timer lastFlying = new MillisTimer();
public Set<Integer> canCreateMob = new HashSet<>();
@@ -43,7 +41,8 @@ public class EntityLocationHandler {
EntityTypes.WITCH, EntityTypes.COW, EntityTypes.CREEPER);
public Optional<Integer> getTargetOfFakeMob(int fakeMobId) {
for (TrackedEntity value : trackedEntities.values()) {
for (TrackedEntity value : data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntities().values()) {
if(value.getFakeMobs().stream().anyMatch(mob -> mob.getEntityId() == fakeMobId)) {
return Optional.of(value.getEntityId());
}
@@ -51,23 +50,6 @@ public class EntityLocationHandler {
return Optional.empty();
}
public Optional<TrackedEntity> getTrackedEntity(int entityId) {
TrackedEntity trackedEntity = trackedEntities.get(entityId);
if(trackedEntity == null) {
var entity = Anticheat.INSTANCE.getWorldInfo(data.getBukkitPlayer().getWorld()).getEntity(entityId);
if(entity.isEmpty()) {
return Optional.empty();
}
KLocation loc = new KLocation(entity.get().getLocation());
trackedEntity = new TrackedEntity(entityId, EntityTypes.PLAYER, loc);
trackedEntities.put(entityId, trackedEntity);
}
return Optional.of(trackedEntity);
}
/**
*
* We are processing PacketPlayInFlying to iterate the tracked entity locations
@@ -81,7 +63,7 @@ public class EntityLocationHandler {
processZombie();
trackedEntities.values().forEach(entity -> {
data.getWorldTracker().getCurrentWorld().get().getTrackedEntities().values().forEach(entity -> {
var oldLoc = entity.getOldEntityLocation();
var newLoc = entity.getNewEntityLocation();
@@ -109,7 +91,8 @@ public class EntityLocationHandler {
* @param packet WrappedOutRelativePosition
*/
void onRelPosition(WPacketPlayOutEntity packet) {
Optional<TrackedEntity> entity = getTrackedEntity(packet.getId());
Optional<TrackedEntity> entity = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(packet.getId());
if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
@@ -132,7 +115,8 @@ public class EntityLocationHandler {
}
void onPositionSync(WrapperPlayServerEntityPositionSync packet) {
Optional<TrackedEntity> entity = getTrackedEntity(packet.getId());
Optional<TrackedEntity> entity = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(packet.getId());
if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
@@ -161,7 +145,8 @@ public class EntityLocationHandler {
* @param packet WrappedOutEntityTeleportPacket
*/
void onTeleportSent(WrapperPlayServerEntityTeleport packet) {
Optional<TrackedEntity> entity = getTrackedEntity(packet.getEntityId());
Optional<TrackedEntity> entity = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(packet.getEntityId());
if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
@@ -205,6 +190,28 @@ public class EntityLocationHandler {
});
}
void updateAttributes(WrapperPlayServerUpdateAttributes attributes) {
data.runKeepaliveAction(ka -> {
TrackedEntity tracked = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(attributes.getEntityId()).orElse(null);
if(tracked == null) return;
for (WrapperPlayServerUpdateAttributes.Property property : attributes.getProperties()) {
Attribute attribute = property.getAttribute();
if(attributes.getEntityId() == data.getBukkitPlayer().getEntityId() && attribute == Attributes.MOVEMENT_SPEED) {
ValuedAttribute value = tracked.getAttribute(attribute);
value.updateAttribute(property);
data.getInfo().setWalkSpeed(value.getValue());
}
tracked.updateAttribute(property);
}
});
}
/**
*
* We are running an action when a transaction is received. If the Entity provided is currently a target,
@@ -239,8 +246,10 @@ public class EntityLocationHandler {
}
public void removeFakeMob(int id) {
if(trackedEntities.containsKey(id)) {
List<FakeMob> mobs = getTrackedEntity(id).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>());
if(data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntities().containsKey(id)) {
List<FakeMob> mobs = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(id).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>());
for (FakeMob mob : mobs) {
mob.despawn();
@@ -256,9 +265,11 @@ public class EntityLocationHandler {
private void createFakeMob(int entityId, KLocation location) {
if (!canCreateMob.contains(entityId)) return;
Optional<TrackedEntity> trackedEntity = getTrackedEntity(entityId);
Optional<TrackedEntity> trackedEntity = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(entityId);
Optional<TrackedEntity> playerEntity = getTrackedEntity(data.getBukkitPlayer().getEntityId());
Optional<TrackedEntity> playerEntity = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(data.getBukkitPlayer().getEntityId());
if(trackedEntity.isEmpty() || playerEntity.isEmpty()) return;
@@ -281,7 +292,7 @@ public class EntityLocationHandler {
RayCollision collision = new RayCollision(eyeLoc.toVector(), eyeLoc.getDirection());
Vector point = collision.collisionPoint(0.4);
Vector3d point = collision.collisionPoint(0.4);
FakeMob mob = new FakeMob(EntityTypes.SLIME);
List<EntityData<?>> types = new ArrayList<>();
@@ -298,7 +309,8 @@ public class EntityLocationHandler {
}
public void processZombie() {
List<FakeMob> fakeMobs = getTrackedEntity(data.getBukkitPlayer().getEntityId())
List<FakeMob> fakeMobs = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(data.getBukkitPlayer().getEntityId())
.map(TrackedEntity::getFakeMobs)
.orElse(new ArrayList<>());
@@ -312,7 +324,7 @@ public class EntityLocationHandler {
RayCollision collision = new RayCollision(eyeLoc.toVector(), eyeLoc.getDirection());
Vector point = collision.collisionPoint(0.4);
Vector3d point = collision.collisionPoint(0.4);
fakeMob.teleport(point.getX(), point.getY(), point.getZ(), 0 ,0);
break;
@@ -321,7 +333,8 @@ public class EntityLocationHandler {
}
public void processFakeMobs(int entityId, boolean rel, double x, double y, double z) {
List<FakeMob> fakeMobs = getTrackedEntity(entityId).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>());
List<FakeMob> fakeMobs = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(entityId).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>());
if(fakeMobs.isEmpty()) {
if(!rel) {
@@ -3,6 +3,7 @@ package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.potion.PotionTypes;
import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
@@ -12,13 +13,13 @@ import dev.brighten.ac.compat.CompatHandler;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.data.obj.CMove;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.objects.evicting.EvictingList;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.types.RayCollision;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.val;
@@ -30,9 +31,6 @@ import me.hydro.emulator.util.Vector;
import me.hydro.emulator.util.mcp.MathHelper;
import me.hydro.emulator.util.mcp.MathHelper.FastMathType;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import java.util.*;
@@ -88,20 +86,13 @@ public class MovementHandler {
private final Timer lastReset = new TickTimer(2);
private final EvictingList<Integer> sensitivitySamples = new EvictingList<>(50);
private boolean modernMovement;
public MovementHandler(APlayer player) {
this.player = player;
Player bplayer = player.getBukkitPlayer();
// Initializing player location
to.setWorld(bplayer.getWorld());
to.getLoc().setX(bplayer.getLocation().getX());
to.getLoc().setY(bplayer.getLocation().getY());
to.getLoc().setZ(bplayer.getLocation().getZ());
to.getLoc().setYaw(bplayer.getLocation().getYaw());
to.getLoc().setPitch(bplayer.getLocation().getPitch());
to.setBox(new SimpleCollisionBox(to.getLoc(), 0.6, 1.8));
to.setOnGround(bplayer.isOnGround());
to.setOnGround(false);
// Setting from as same location as to
from.setLoc(to);
@@ -123,31 +114,32 @@ public class MovementHandler {
*/
final PotionEffect[] EFFECTS = new PotionEffect[3];
for (org.bukkit.potion.PotionEffect potionEffect : player.getPotionHandler().potionEffects) {
if (potionEffect.getType().equals(PotionEffectType.SPEED)) {
for (KPotionEffect potionEffect : player.getPotionHandler().getPotionEffects()) {
if (potionEffect.potionType().equals(PotionTypes.SPEED)) {
EFFECTS[0] = PotionEffect.builder()
.amplifier(potionEffect.getAmplifier())
.amplifier(potionEffect.properties().amplifier())
.type(me.hydro.emulator.util.PotionEffectType.SPEED)
.build();
} else if (potionEffect.getType().equals(PotionEffectType.SLOW)) {
} else if (potionEffect.potionType().equals(PotionTypes.SLOWNESS)) {
EFFECTS[1] = PotionEffect.builder()
.amplifier(potionEffect.getAmplifier())
.amplifier(potionEffect.properties().amplifier())
.type(me.hydro.emulator.util.PotionEffectType.SLOW)
.build();
} else if (potionEffect.getType().equals(PotionEffectType.JUMP)) {
} else if (potionEffect.potionType().equals(PotionTypes.JUMP_BOOST)) {
EFFECTS[2] = PotionEffect.builder()
.amplifier(potionEffect.getAmplifier())
.amplifier(potionEffect.properties().amplifier())
.type(me.hydro.emulator.util.PotionEffectType.JUMP)
.build();
}
}
if(player.EMULATOR.getTags().contains("003") && !isZeroThree) {
if (player.EMULATOR.getTags().contains("003") && !isZeroThree) {
runEmulation(to, true);
}
IterationResult minimum = null;
iteration: {
iteration:
{
for (KLocation posLoc : new ArrayList<>(posLocs)) {
// Resetting to prevent lag issues.
@@ -157,7 +149,7 @@ public class MovementHandler {
if (minimum == null || minimum.getOffset() > result.getOffset()) {
minimum = result;
if(minimum.getOffset() < 1E-26) {
if (minimum.getOffset() < 1E-26) {
// The player teleported, therefore we don't need to continue with predictions.
break iteration;
}
@@ -171,83 +163,180 @@ public class MovementHandler {
Motion previousMotion = player.EMULATOR.getMotion().clone();
for (int forward : isZeroThree ? new int[] {0} : FULL_RANGE) {
for (int strafe : isZeroThree ? new int[] {0} : FULL_RANGE) {
for (boolean jumping : getJumpingIterations()) {
for (boolean sprinting : getSprintingIterations(forward)) {
for (boolean usingItem : getUsingItemIterations(forward, strafe)) {
for (boolean hitSlow : getHitSlowIterations()) {
for (FastMathType fastMath : getFastMathIterations(forward, strafe)) {
for(Vector3d possibleVector : possibleVelocity) {
IterationInput input = IterationInput.builder()
.jumping(jumping)
.forward(forward)
.strafing(strafe)
.sprinting(sprinting)
.usingItem(usingItem)
.modernMovement(modernMovement)
.hitSlowdown(hitSlow)
.aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2)
.fastMathType(fastMath)
.sneaking(player.getInfo().isSneaking())
.ground(from.isOnGround())
.to(new Vector(to.getX(), to.getY(), to.getZ()))
.yaw(to.getYaw())
.lastReportedBoundingBox(from.getBox().toNeo())
.effectSpeed(EFFECTS[0])
.effectSlow(EFFECTS[1])
.waitingForTeleport(!posLocs.isEmpty())
.effectJump(EFFECTS[2]).build();
boolean isVelocity = false;
if(possibleVector != null) {
// Setting the motion to the possible velocity vector.
player.EMULATOR.getMotion().setMotionX(possibleVector.getX());
player.EMULATOR.getMotion().setMotionY(possibleVector.getY());
player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ());
// Has to be this way because order of operations in the emulator.
isVelocity = true;
} else {
// Resetting the motion to the previous motion.
player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX());
player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY());
player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ());
}
if(player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_21)) {
var playerInput = player.getInfo().getPlayerInput();
int forward = 0, strafe = 0;
IterationResult result = player.EMULATOR.runIteration(input);
if(playerInput.forward()) {
forward = 1;
} else if(playerInput.backward()) {
forward = -1;
}
if(isVelocity) {
result.getTags().add("velocity");
}
if(playerInput.left()) {
strafe = -1;
} else if(playerInput.right()) {
strafe = 1;
}
for (boolean usingItem : getUsingItemIterations(forward, strafe)) {
for (boolean hitSlow : getHitSlowIterations()) {
for (FastMathType fastMath : getFastMathIterations(forward, strafe)) {
for (Vector3d possibleVector : possibleVelocity) {
IterationInput input = IterationInput.builder()
.jumping(playerInput.jump())
.forward(forward)
.strafing(strafe)
.sprinting(playerInput.sprint())
.usingItem(usingItem)
.modernMovement(modernMovement)
.hitSlowdown(hitSlow)
.aiMoveSpeed(player.getInfo().getWalkSpeed() / 2)
.fastMathType(fastMath)
.sneaking(player.getInfo().isSneaking())
.ground(from.isOnGround())
.to(new Vector(to.getX(), to.getY(), to.getZ()))
.yaw(to.getYaw())
.lastReportedBoundingBox(from.getBox().toNeo())
.effectSpeed(EFFECTS[0])
.effectSlow(EFFECTS[1])
.waitingForTeleport(!posLocs.isEmpty())
.effectJump(EFFECTS[2]).build();
boolean isVelocity = false;
if (possibleVector != null) {
// Setting the motion to the possible velocity vector.
player.EMULATOR.getMotion().setMotionX(possibleVector.getX());
player.EMULATOR.getMotion().setMotionY(possibleVector.getY());
player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ());
// Has to be this way because order of operations in the emulator.
isVelocity = true;
} else {
// Resetting the motion to the previous motion.
player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX());
player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY());
player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ());
}
IterationResult result = player.EMULATOR.runIteration(input);
if (isVelocity) {
result.getTags().add("velocity");
}
if(fastMath == FastMathType.FAST_LEGACY) {
result.getTags().add("fast_legacy");
} else if(fastMath == FastMathType.VANILLA) {
result.getTags().add("vanilla");
} else if(fastMath == FastMathType.FAST_NEW) {
result.getTags().add("fast_new");
} else if(fastMath == FastMathType.MODERN_VANILLA) {
result.getTags().add("modern_vanilla");
}
if (fastMath == FastMathType.FAST_LEGACY) {
result.getTags().add("fast_legacy");
} else if (fastMath == FastMathType.VANILLA) {
result.getTags().add("vanilla");
} else if (fastMath == FastMathType.FAST_NEW) {
result.getTags().add("fast_new");
} else if (fastMath == FastMathType.MODERN_VANILLA) {
result.getTags().add("modern_vanilla");
}
if(forward > 0) {
result.getTags().add("w-key");
} else if(forward < 0) {
result.getTags().add("s-key");
}
if (forward > 0) {
result.getTags().add("w-key");
} else if (forward < 0) {
result.getTags().add("s-key");
}
if(strafe > 0) {
result.getTags().add("d-key");
} else if(strafe < 0) {
result.getTags().add("a-key");
}
if (strafe > 0) {
result.getTags().add("d-key");
} else if (strafe < 0) {
result.getTags().add("a-key");
}
if (minimum == null || minimum.getOffset() > result.getOffset()) {
minimum = result;
if (minimum == null || minimum.getOffset() > result.getOffset()) {
minimum = result;
if (minimum.getOffset() < 1E-26) {
break iteration;
if (minimum.getOffset() < 1E-26) {
break iteration;
}
}
}
}
}
}
} else {
for (int forward : isZeroThree ? new int[]{0} : FULL_RANGE) {
for (int strafe : isZeroThree ? new int[]{0} : FULL_RANGE) {
for (boolean jumping : getJumpingIterations()) {
for (boolean sprinting : getSprintingIterations(forward)) {
for (boolean usingItem : getUsingItemIterations(forward, strafe)) {
for (boolean hitSlow : getHitSlowIterations()) {
for (FastMathType fastMath : getFastMathIterations(forward, strafe)) {
for (Vector3d possibleVector : possibleVelocity) {
IterationInput input = IterationInput.builder()
.jumping(jumping)
.forward(forward)
.strafing(strafe)
.sprinting(sprinting)
.usingItem(usingItem)
.modernMovement(modernMovement)
.hitSlowdown(hitSlow)
.aiMoveSpeed(player.getInfo().getWalkSpeed() / 2)
.fastMathType(fastMath)
.sneaking(player.getInfo().isSneaking())
.ground(from.isOnGround())
.to(new Vector(to.getX(), to.getY(), to.getZ()))
.yaw(to.getYaw())
.lastReportedBoundingBox(from.getBox().toNeo())
.effectSpeed(EFFECTS[0])
.effectSlow(EFFECTS[1])
.waitingForTeleport(!posLocs.isEmpty())
.effectJump(EFFECTS[2]).build();
boolean isVelocity = false;
if (possibleVector != null) {
// Setting the motion to the possible velocity vector.
player.EMULATOR.getMotion().setMotionX(possibleVector.getX());
player.EMULATOR.getMotion().setMotionY(possibleVector.getY());
player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ());
// Has to be this way because order of operations in the emulator.
isVelocity = true;
} else {
// Resetting the motion to the previous motion.
player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX());
player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY());
player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ());
}
IterationResult result = player.EMULATOR.runIteration(input);
if (isVelocity) {
result.getTags().add("velocity");
}
if (fastMath == FastMathType.FAST_LEGACY) {
result.getTags().add("fast_legacy");
} else if (fastMath == FastMathType.VANILLA) {
result.getTags().add("vanilla");
} else if (fastMath == FastMathType.FAST_NEW) {
result.getTags().add("fast_new");
} else if (fastMath == FastMathType.MODERN_VANILLA) {
result.getTags().add("modern_vanilla");
}
if (forward > 0) {
result.getTags().add("w-key");
} else if (forward < 0) {
result.getTags().add("s-key");
}
if (strafe > 0) {
result.getTags().add("d-key");
} else if (strafe < 0) {
result.getTags().add("a-key");
}
if (minimum == null || minimum.getOffset() > result.getOffset()) {
minimum = result;
if (minimum.getOffset() < 1E-26) {
break iteration;
}
}
}
}
@@ -259,8 +348,7 @@ public class MovementHandler {
}
}
}
if(minimum != null) {
if (minimum != null) {
predicted = minimum.getPredicted();
double mx = player.EMULATOR.getMotion().getMotionX();
@@ -269,7 +357,7 @@ public class MovementHandler {
double total = mx * mx + my * my + mz * mz;
if(total < 9E-4) {
if (total < 9E-4) {
player.getInfo().lastCanceledFlying.reset();
minimum.getTags().add("003");
}
@@ -282,11 +370,11 @@ public class MovementHandler {
}
player.EMULATOR.confirm(minimum.getIteration());
if(minimum.getTags().contains("003")) {
if (minimum.getTags().contains("003")) {
player.EMULATOR.getTags().add("003");
}
if(minimum.getTags().contains("bad_offset")) {
if (minimum.getTags().contains("bad_offset")) {
player.EMULATOR.setLastReportedBoundingBox(getTo().getBox().toNeo());
}
}
@@ -294,7 +382,7 @@ public class MovementHandler {
private FastMathType[] getFastMathIterations(int strafe, int forward) {
// Because no movement is being applied, there is no angle calculation being done
if(strafe == 0 && forward == 0) {
if (strafe == 0 && forward == 0) {
return new FastMathType[]{FastMathType.FAST_LEGACY};
}
@@ -317,7 +405,9 @@ public class MovementHandler {
private boolean[] getUsingItemIterations(int forward, int strafe) {
return (forward == 0 && strafe == 0 ||
!BlockUtils.isUsable(player.getBukkitPlayer().getItemInHand().getType())) ? ALWAYS_FALSE : IS_OR_NOT;
!BlockUtils.isUsable(player.getPlayerVersion(),
SpigotConversionUtil.fromBukkitItemMaterial(player.getBukkitPlayer().getInventory().getItemInHand().getType())))
? ALWAYS_FALSE : IS_OR_NOT;
}
private boolean[] getJumpingIterations() {
@@ -336,13 +426,13 @@ public class MovementHandler {
&& player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17);
checkMovement = teleportsToConfirm == 0 && posLocs.isEmpty();
if (checkMovement) {
moveTicks++;
if (!packet.hasPositionChanged()) moveTicks = 1;
} else moveTicks = 0;
if(excuseNextFlying) {
if (excuseNextFlying) {
return;
}
@@ -359,10 +449,10 @@ public class MovementHandler {
if (moveTicks > 0) {
// Updating block locations
player.getInfo().setBlockOnTo(Optional.of(player.getBlockUpdateHandler()
.getBlock(new IntVector(to.getLoc()))));
player.getInfo().setBlockBelow(Optional.of(player.getBlockUpdateHandler()
.getBlock(new IntVector(to.getLoc().clone().subtract(0, 1, 0)))));
player.getInfo().setBlockOnTo(Optional.of(player.getWorldTracker()
.getBlock(to.getLoc().toVector3i())));
player.getInfo().setBlockBelow(Optional.of(player.getWorldTracker()
.getBlock(to.getLoc().clone().subtract(0, 1, 0).clone().toVector3i())));
if (packet.hasPositionChanged()) {
// Updating player bounding box
@@ -486,7 +576,7 @@ public class MovementHandler {
player.getInfo().setWasOnSlime(player.getBlockInfo().onSlime);
groundTicks++;
airTicks = 0;
player.getInfo().groundJumpBoost = player.getPotionHandler().getEffectByType(PotionEffectType.JUMP);
player.getInfo().groundJumpBoost = player.getPotionHandler().getEffectByType(PotionTypes.JUMP_BOOST);
} else {
player.getInfo().groundJumpBoost = Optional.empty();
airTicks++;
@@ -503,7 +593,7 @@ public class MovementHandler {
.anyMatch(capability -> capability.canFly));
boolean hasLevitation = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)
&& player.getPotionHandler().hasPotionEffect(XPotion.LEVITATION.getPotionEffectType());
&& player.getPotionHandler().hasPotionEffect(PotionTypes.LEVITATION);
player.getInfo().setRiptiding(CompatHandler.getINSTANCE().isRiptiding(player.getBukkitPlayer()));
player.getInfo().setGliding(CompatHandler.getINSTANCE().isGliding(player.getBukkitPlayer()));
@@ -570,7 +660,7 @@ it
// generate a method that processes velocityHistory and compares to current deltaY.
private void processVelocity() {
//Iterate through player.getInfo().getVelocityHistory() and compare to current deltaY.
if(player.getInfo().isDoingVelocity()) {
if (player.getInfo().isDoingVelocity()) {
player.getInfo().getVelocity().reset();
}
synchronized (player.getInfo().getVelocityHistory()) {
@@ -590,22 +680,22 @@ it
}
private void processBotMove(WrapperPlayClientPlayerFlying packet) {
if(player.getMob() == null) return;
if (player.getMob() == null) return;
if (packet.hasPositionChanged() || packet.hasRotationChanged()) {
KLocation origin = to.getLoc().clone().add(0, 1.7, 0);
final double MULTIPLIER = Math.max(-0.5, Math.min(-1, -1 / (Math.abs(deltaYaw) * 0.25)));
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection()
.multiply(MULTIPLIER).setY(0));
.multiply(MULTIPLIER).withY(0));
Location loc1 = coll.collisionPoint(1.5).toLocation(player.getBukkitPlayer().getWorld());
KLocation loc1 = new KLocation(coll.collisionPoint(1.5));
if (player.getInfo().botAttack.isNotPassed(7)) {
loc1.setY(Math.max(origin.getY() + 2, loc1.getY()));
player.getMob().teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch());
} else {
loc1.setY(Math.max(origin.getY() + 0.6, loc1.getY()));
if(Math.random() > 0.2)
if (Math.random() > 0.2)
Anticheat.INSTANCE.getRunUtils().taskLaterAsync(() -> player.getMob()
.teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch()), 5);
}
@@ -661,7 +751,7 @@ it
public void runPositionHackFix() {
if (sentPositionUpdate) return;
player.sendPacket(new WrapperPlayServerPlayerPositionAndLook(0, Vector3d.zero(), new Vector3d(0,0,0), 0, 0,
player.sendPacket(new WrapperPlayServerPlayerPositionAndLook(0, Vector3d.zero(), new Vector3d(0, 0, 0), 0, 0,
relFlags));
player.getBukkitPlayer().sendMessage("§c[Anticheat] §7Position update sent to fix movement issues.");
@@ -725,10 +815,10 @@ it
packet.getYaw(), packet.getPitch());
if (packet.getRelativeFlags().has(RelativeFlag.X)) {
loc.add(player.getMovement().getTo().getLoc().getX(), 0 ,0);
loc.add(player.getMovement().getTo().getLoc().getX(), 0, 0);
}
if (packet.getRelativeFlags().has(RelativeFlag.Y)) {
loc.add(0, player.getMovement().getTo().getLoc().getY() ,0);
loc.add(0, player.getMovement().getTo().getLoc().getY(), 0);
}
if (packet.getRelativeFlags().has(RelativeFlag.Z)) {
loc.add(0, 0, player.getMovement().getTo().getLoc().getZ());
@@ -743,7 +833,6 @@ it
teleportsToConfirm++;
loc.setTimeStamp(System.currentTimeMillis());
player.runKeepaliveAction(ka -> {
teleportsToConfirm--;
@@ -762,7 +851,7 @@ it
*
* @param location Location
*/
public void moveTo(Location location) {
public void moveTo(KLocation location) {
KLocation newLoc = new KLocation(location);
to.getLoc().setLocation(newLoc);
to.getLoc().setLocation(newLoc);
@@ -814,7 +903,7 @@ it
* @param packet WrapperPlayClientPlayerFlyingh
*/
private void setTo(WrapperPlayClientPlayerFlying packet) {
to.setWorld(player.getBukkitPlayer().getWorld());
to.setWorld(player.getWorldTracker().getCurrentWorld().get());
if (packet.hasPositionChanged()) {
to.getLoc().setX(packet.getLocation().getX());
to.getLoc().setY(packet.getLocation().getY());
@@ -18,6 +18,8 @@ import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.data.info.PlayerInput;
import dev.brighten.ac.data.obj.Pose;
import dev.brighten.ac.handler.entity.FakeMob;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.packet.PlayerCapabilities;
@@ -26,10 +28,7 @@ import dev.brighten.ac.packet.WPacketPlayOutEntity;
import dev.brighten.ac.utils.BlockUtils;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.MovementUtils;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.val;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import java.util.Optional;
@@ -38,13 +37,14 @@ public class PacketHandler {
public boolean processReceive(APlayer player, PacketReceiveEvent event) {
long timestamp = System.currentTimeMillis();
Object wrapped;
if (event.getPacketType().equals(PacketType.Play.Client.PONG)
|| event.getPacketType().equals(PacketType.Play.Client.WINDOW_CONFIRMATION)) {
boolean cancel = false;
if (event.getPacketType().equals(PacketType.Play.Client.PONG) || event.getPacketType().equals(PacketType.Play.Client.WINDOW_CONFIRMATION)) {
TransactionClientWrapper packet = new TransactionClientWrapper(event);
wrapped = packet;
if(packet.getId() == 0) {
if (packet.getId() == 0) {
if (Anticheat.INSTANCE.getKeepaliveProcessor().keepAlives.get(packet.getAction()) != null) {
Anticheat.INSTANCE.getKeepaliveProcessor().addResponse(player, packet.getAction());
@@ -68,7 +68,7 @@ public class PacketHandler {
synchronized (player.instantTransaction) {
var iterator = player.instantTransaction.keySet().iterator();
while(iterator.hasNext()) {
while (iterator.hasNext()) {
Short key = iterator.next();
if (key > ka.id) {
@@ -96,7 +96,7 @@ public class PacketHandler {
synchronized (player.keepAliveLock) {
player.keepAliveStamps.removeIf(action -> {
if(action.stamp > ka.id) {
if (action.stamp > ka.id) {
return false;
}
@@ -110,10 +110,17 @@ public class PacketHandler {
Optional.ofNullable(player.instantTransaction.remove(packet.getAction()))
.ifPresent(t -> t.two.accept(t.one));
}
} else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION)
|| event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION)
|| event.getPacketType().equals(PacketType.Play.Client.PLAYER_ROTATION)
|| event.getPacketType().equals(PacketType.Play.Client.PLAYER_FLYING)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_INPUT)) {
WrapperPlayClientPlayerInput packet = new WrapperPlayClientPlayerInput(event);
wrapped = packet;
player.getInfo().setSprinting(packet.isSprint());
player.getInfo().setSneaking(packet.isShift());
player.getInfo().setPlayerInput(PlayerInput.getFromPacket(packet));
player.getBukkitPlayer().sendMessage("packet: " + packet.isForward());
} else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) || event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION) || event.getPacketType().equals(PacketType.Play.Client.PLAYER_ROTATION) || event.getPacketType().equals(PacketType.Play.Client.PLAYER_FLYING)) {
WrapperPlayClientPlayerFlying packet = new WrapperPlayClientPlayerFlying(event);
wrapped = packet;
if (player.getMovement().isExcuseNextFlying()) {
@@ -127,7 +134,7 @@ public class PacketHandler {
player.getLagInfo().setLastFlying(timestamp);
player.getEntityLocationHandler().onFlying();
player.getEntityTrackHandler().onFlying();
if (player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17)
&& packet.hasPositionChanged() && packet.hasRotationChanged()
@@ -145,17 +152,17 @@ public class PacketHandler {
player.getVelocityHandler().onFlyingPost(packet);
return result;
} else if(event.getPacketType().equals(PacketType.Play.Client.STEER_VEHICLE)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.STEER_VEHICLE)) {
WrapperPlayClientSteerVehicle packet = new WrapperPlayClientSteerVehicle(event);
wrapped = packet;
// Check for isUnmount()
if (player.getBukkitPlayer().isInsideVehicle() && packet.isUnmount()) {
if (player.getInfo().isInVehicle() && packet.isUnmount()) {
player.getInfo().getVehicleSwitch().reset();
player.getInfo().setInVehicle(false);
}
} else if(event.getPacketType().equals(PacketType.Play.Client.ENTITY_ACTION)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.ENTITY_ACTION)) {
WrapperPlayClientEntityAction packet = new WrapperPlayClientEntityAction(event);
wrapped = packet;
@@ -178,13 +185,13 @@ public class PacketHandler {
break;
}
case START_FLYING_WITH_ELYTRA: {
if(player.isGlidePossible()) {
if (player.isGlidePossible()) {
player.getInfo().setGliding(true);
}
break;
}
}
} else if(event.getPacketType().equals(PacketType.Play.Client.INTERACT_ENTITY)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.INTERACT_ENTITY)) {
WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event);
wrapped = packet;
@@ -192,39 +199,44 @@ public class PacketHandler {
FakeMob mob = Anticheat.INSTANCE.getFakeTracker().getEntityById(packet.getEntityId());
if (packet.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
if (player.hitsToCancel > 0) {
player.hitsToCancel--;
cancel = true;
}
if (mob != null) {
player.getEntityLocationHandler().getTargetOfFakeMob(mob.getEntityId())
player.getEntityTrackHandler().getTargetOfFakeMob(mob.getEntityId())
.ifPresent(targetId -> {
player.getEntityLocationHandler().removeFakeMob(targetId);
player.getEntityTrackHandler().removeFakeMob(targetId);
player.getInfo().lastFakeBotHit.reset();
});
if (player.getMob().getEntityId() == packet.getEntityId()) {
player.getInfo().botAttack.reset();
}
} else {
Optional<Entity> target = Anticheat.INSTANCE.getWorldInfo(player.getBukkitPlayer().getWorld()).getEntity(packet.getEntityId());
Optional<TrackedEntity> target = player.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(packet.getEntityId());
if(target.isPresent() && target.get() instanceof LivingEntity entity) {
if (target.isPresent() && target.get().getEntityType().isInstanceOf(EntityTypes.LIVINGENTITY)) {
if (player.getInfo().lastFakeBotHit.isPassed(400) && Math.random() > 0.9) {
player.getEntityLocationHandler().canCreateMob.add(entity.getEntityId());
player.getEntityTrackHandler().canCreateMob.add(target.get().getEntityId());
}
player.getInfo().setTarget(entity);
player.getInfo().setTarget(target.get());
}
}
player.getInfo().lastAttack.reset();
}
} else if(event.getPacketType().equals(PacketType.Play.Client.ANIMATION)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.ANIMATION)) {
WrapperPlayClientAnimation packet = new WrapperPlayClientAnimation(event);
wrapped = packet;
if(packet.getHand() == InteractionHand.MAIN_HAND) {
if (packet.getHand() == InteractionHand.MAIN_HAND) {
long delta = timestamp - player.getInfo().lastArmSwing;
player.getInfo().cps.add(1000D / delta, timestamp);
player.getInfo().lastArmSwing = timestamp;
}
} else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT)) {
WrapperPlayClientPlayerBlockPlacement packet = new WrapperPlayClientPlayerBlockPlacement(event);
wrapped = packet;
@@ -236,19 +248,19 @@ public class PacketHandler {
// Used item
if (pos.getX() == -1 && (pos.getY() == 255 | pos.getY() == -1) && pos.getZ() == -1
&& stack.isPresent()
&& BlockUtils.isUsable(SpigotConversionUtil.toBukkitItemMaterial(stack.get().getType()))) {
&& BlockUtils.isUsable(player.getPlayerVersion(), stack.get().getType())) {
player.getInfo().getLastUseItem().reset();
}
player.getBlockUpdateHandler().onPlace(packet);
} else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_DIGGING)) {
player.getWorldTracker().onPlace(packet);
} else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_DIGGING)) {
WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
wrapped = packet;
player.getInfo().getLastBlockDig().reset();
player.getBlockUpdateHandler().onDig(packet);
} else if(event.getPacketType().equals(PacketType.Play.Client.CLIENT_STATUS)) {
player.getWorldTracker().onDig(packet);
} else if (event.getPacketType().equals(PacketType.Play.Client.CLIENT_STATUS)) {
WrapperPlayClientClientStatus packet = new WrapperPlayClientClientStatus(event);
wrapped = packet;
@@ -258,10 +270,10 @@ public class PacketHandler {
player.getInfo().lastInventoryOpen.reset();
return false;
}
} else if(event.getPacketType().equals(PacketType.Play.Client.CLOSE_WINDOW)) {
} else if (event.getPacketType().equals(PacketType.Play.Client.CLOSE_WINDOW)) {
wrapped = new WrapperPlayClientCloseWindow(event);
player.getInfo().setInventoryOpen(false);
} else if(event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE) {
} else if (event.getPacketType().equals(PacketType.Play.Client.PLUGIN_MESSAGE)) {
WrapperPlayClientPluginMessage packet = new WrapperPlayClientPluginMessage(event);
wrapped = packet;
@@ -286,7 +298,7 @@ public class PacketHandler {
+ ": " + wrapped);
}
return player.getCheckHandler().callSyncPacket(wrapped, timestamp);
return cancel || player.getCheckHandler().callSyncPacket(wrapped, timestamp);
}
public boolean processSend(APlayer player, PacketSendEvent event) {
@@ -309,30 +321,36 @@ public class PacketHandler {
player.getInfo().getPossibleCapabilities().clear();
}
}, true);
} else if(event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) {
WrapperPlayServerUpdateAttributes packet = new WrapperPlayServerUpdateAttributes(event);
wrapped = packet;
player.getEntityTrackHandler().updateAttributes(packet);
} else if(event.getPacketType() == PacketType.Play.Server.BLOCK_CHANGE) {
WrapperPlayServerBlockChange packet = new WrapperPlayServerBlockChange(event);
wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet);
player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.MULTI_BLOCK_CHANGE) {
WrapperPlayServerMultiBlockChange packet = new WrapperPlayServerMultiBlockChange(event);
wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet);
player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.CHUNK_DATA) {
WrapperPlayServerChunkData packet = new WrapperPlayServerChunkData(event);
wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet);
player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.MAP_CHUNK_BULK) {
WrapperPlayServerChunkDataBulk packet = new WrapperPlayServerChunkDataBulk(event);
wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet);
player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) {
WrapperPlayServerEntityEffect packet = new WrapperPlayServerEntityEffect(event);
@@ -394,18 +412,19 @@ public class PacketHandler {
} else if(event.getPacketType() == PacketType.Play.Server.RESPAWN) {
wrapped = new WrapperPlayServerRespawn(event);
if(player.getPlayerVersion().isOlderThan(ClientVersion.V_1_14)) {
player.runKeepaliveAction(k -> player.getBukkitPlayer().setSprinting(false), 1);
player.runKeepaliveAction(k -> player.getInfo().setSprinting(false), 1);
}
player.runKeepaliveAction(ka -> player.getInfo().lastRespawn.reset());
player.runKeepaliveAction(ka -> player.getBlockUpdateHandler()
.setMinHeight(player.getDimensionType()));
player.runKeepaliveAction(ka -> {
player.getInfo().lastRespawn.reset();
player.getInfo().setPose(Pose.STANDING);
});
player.runKeepaliveAction(ka -> player.getWorldTracker()
.onRespawn((WrapperPlayServerRespawn) wrapped));
} else if(event.getPacketType() == PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) {
WrapperPlayServerPlayerPositionAndLook packet = new WrapperPlayServerPlayerPositionAndLook(event);
wrapped = packet;
player.runKeepaliveAction(ka ->
player.getBlockUpdateHandler().setMinHeight(player.getDimensionType()));
player.getMovement().addPosition(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) {
WrapperPlayServerAttachEntity packet = new WrapperPlayServerAttachEntity(event);
@@ -423,37 +442,37 @@ public class PacketHandler {
wrapped = packet;
player.getEntityLocationHandler().onEntityDestroy(packet);
player.getEntityTrackHandler().onEntityDestroy(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) {
WrapperPlayServerEntityTeleport packet = new WrapperPlayServerEntityTeleport(event);
wrapped = packet;
player.getEntityLocationHandler().onTeleportSent(packet);
player.getEntityTrackHandler().onTeleportSent(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_MOVEMENT) {
WrapperPlayServerEntityMovement packet = new WrapperPlayServerEntityMovement(event);
wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet));
player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) {
WrapperPlayServerEntityRelativeMove packet = new WrapperPlayServerEntityRelativeMove(event);
wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet));
player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) {
WrapperPlayServerEntityRotation packet = new WrapperPlayServerEntityRotation(event);
wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet));
player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION) {
WrapperPlayServerEntityRelativeMoveAndRotation packet = new WrapperPlayServerEntityRelativeMoveAndRotation(event);
wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet));
player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
wrapped = packet;
@@ -462,7 +481,7 @@ public class PacketHandler {
double y = packet.getPosition().getY();
double z = packet.getPosition().getZ();
player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(),
player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(),
new TrackedEntity(packet.getEntityId(), packet.getEntityType(),
new KLocation(x, y, z, packet.getYaw(), packet.getPitch())));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
@@ -474,7 +493,7 @@ public class PacketHandler {
double y = packet.getPosition().getY();
double z = packet.getPosition().getZ();
player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(),
player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(),
new TrackedEntity(packet.getEntityId(), packet.getEntityType(),
new KLocation(x, y, z, packet.getYaw(), packet.getPitch())));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) {
@@ -487,7 +506,7 @@ public class PacketHandler {
double z = packet.getPosition().getZ();
player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(),
player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(),
new TrackedEntity(packet.getEntityId(), EntityTypes.PLAYER,
new KLocation(x, y, z, packet.getYaw(),packet.getPitch())));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) {
@@ -499,14 +518,14 @@ public class PacketHandler {
int y = packet.getPosition().getY();
int z = packet.getPosition().getZ();
player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(),
player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(),
new TrackedEntity(packet.getEntityId(), EntityTypes.PAINTING, new KLocation(x, y, z)));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_POSITION_SYNC) {
WrapperPlayServerEntityPositionSync packet = new WrapperPlayServerEntityPositionSync(event);
wrapped = packet;
player.getEntityLocationHandler().onPositionSync(packet);
player.getEntityTrackHandler().onPositionSync(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
wrapped = new WrapperPlayServerEntityMetadata(event);
}else if(event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
@@ -514,7 +533,7 @@ public class PacketHandler {
wrapped = packet;
player.getEntityLocationHandler().onEntityDestroy(packet);
player.getEntityTrackHandler().onEntityDestroy(packet);
} else if(event.getPacketType() == PacketType.Play.Server.CLOSE_WINDOW) {
wrapped = new WrapperPlayServerCloseWindow(event);
player.runKeepaliveAction(ka -> player.getInfo().setInventoryOpen(false));
@@ -1,59 +1,118 @@
package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.protocol.potion.PotionType;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.KPotionEffect;
import dev.brighten.ac.utils.KProperties;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class PotionHandler {
private final APlayer data;
public List<PotionEffect> potionEffects = new CopyOnWriteArrayList<>();
private final List<KPotionEffect> potionEffects = new ArrayList<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public PotionHandler(APlayer data) {
public PotionHandler(APlayer data) {
this.data = data;
potionEffects.addAll(data.getBukkitPlayer().getActivePotionEffects());
lock.writeLock().lock();
try {
data.getBukkitPlayer().getActivePotionEffects().stream()
.map(pe ->
new KPotionEffect(
SpigotConversionUtil.fromBukkitPotionEffectType(pe.getType()),
KProperties.fromBukkit(pe)
))
.forEach(potionEffects::add);
} finally {
lock.writeLock().unlock();
}
}
public void onFlying(WrapperPlayClientPlayerFlying packet) {
for (PotionEffect effect : potionEffects) {
if(data.getBukkitPlayer().hasPotionEffect(effect.getType())) continue;
lock.readLock().lock();
try {
for (KPotionEffect effect : potionEffects) {
lock.readLock().lock();
data.runKeepaliveAction(d -> data.getPotionHandler().potionEffects.remove(effect));
try {
if (data.getBukkitPlayer().hasPotionEffect(SpigotConversionUtil.toBukkitPotionEffectType(effect.potionType()))) continue;
data.runKeepaliveAction(d -> {
lock.writeLock().lock();
try {
data.getPotionHandler().potionEffects.remove(effect);
} finally {
lock.writeLock().unlock();
}
});
} finally {
lock.readLock().unlock();
}
}
} finally {
lock.readLock().unlock();
}
}
public void onPotionEffect(WrapperPlayServerEntityEffect packet) {
data.runKeepaliveAction(d -> {
var type = SpigotConversionUtil.toBukkitPotionEffectType(packet.getPotionType());
data.getPotionHandler().potionEffects.stream().filter(pe -> pe.getType().equals(type))
.forEach(data.getPotionHandler().potionEffects::remove);
data.getPotionHandler().potionEffects
.add(new PotionEffect(type, packet.getEffectDurationTicks(), packet.getEffectAmplifier(),
packet.isAmbient()));
var type = packet.getPotionType();
lock.writeLock().lock();
try {
data.getPotionHandler().potionEffects.removeIf(pe -> pe.potionType().equals(type));
data.getPotionHandler().potionEffects
.add(new KPotionEffect(type, new KProperties(packet.getEffectAmplifier()
, packet.getEffectDurationTicks(),
packet.isAmbient(), packet.isVisible(), packet.isShowIcon(), null)));
} finally {
lock.readLock().unlock();
}
});
}
public boolean hasPotionEffect(PotionEffectType type) {
for (PotionEffect potionEffect : potionEffects) {
if(potionEffect.getType().equals(type))
return true;
public boolean hasPotionEffect(PotionType type) {
lock.readLock().lock();
try {
for (KPotionEffect potionEffect : potionEffects) {
if (potionEffect.potionType().equals(type))
return true;
}
return false;
} finally {
lock.readLock().unlock();
}
return false;
}
public Optional<PotionEffect> getEffectByType(PotionEffectType type) {
for (PotionEffect potionEffect : potionEffects) {
if(potionEffect.getType().equals(type))
return Optional.of(potionEffect);
public Optional<KPotionEffect> getEffectByType(PotionType type) {
lock.readLock().lock();
try {
for (KPotionEffect potionEffect : potionEffects) {
if (potionEffect.potionType().equals(type))
return Optional.of(potionEffect);
}
return Optional.empty();
} finally {
lock.readLock().unlock();
}
return Optional.empty();
}
}
public List<KPotionEffect> getPotionEffects() {
lock.readLock().lock();
try {
return new ArrayList<>(potionEffects);
} finally {
lock.readLock().unlock();
}
}
}
@@ -0,0 +1,49 @@
package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.protocol.attribute.Attribute;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
import lombok.Getter;
import lombok.Setter;
import me.hydro.emulator.util.mcp.MathHelper;
import java.util.Objects;
@Getter
public class ValuedAttribute {
private final Attribute attribute;
@Setter
private WrapperPlayServerUpdateAttributes.Property property;
private double value;
public ValuedAttribute(Attribute attribute) {
this.attribute = attribute;
this.value = attribute.getDefaultValue();
}
public void updateAttribute(WrapperPlayServerUpdateAttributes.Property property) {
this.property = property;
double multiplier = 1, additional = 0, base = 0;
for (WrapperPlayServerUpdateAttributes.PropertyModifier modifier : property.getModifiers()) {
switch (modifier.getOperation()) {
case ADDITION -> additional += modifier.getAmount();
case MULTIPLY_BASE -> base += modifier.getAmount();
case MULTIPLY_TOTAL -> multiplier*= (1 + modifier.getAmount());
}
}
this.value = MathHelper.clamp_double((property.getValue() + additional) * (1 - base) * multiplier,
attribute.getMinValue(), attribute.getMaxValue());
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ValuedAttribute that)) return false;
return Objects.equals(attribute, that.attribute);
}
@Override
public int hashCode() {
return Objects.hash(attribute);
}
}
@@ -1,63 +1,68 @@
package dev.brighten.ac.handler.block;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.player.DiggingAction;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.Column;
import com.github.retrooper.packetevents.protocol.world.chunk.TileEntity;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_16.Chunk_v1_9;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_7.Chunk_v1_7;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_8.Chunk_v1_8;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v_1_18.Chunk_v1_18;
import com.github.retrooper.packetevents.protocol.world.chunk.palette.PaletteType;
import com.github.retrooper.packetevents.protocol.world.dimension.DimensionType;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBlockChange;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChunkData;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChunkDataBulk;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange;
import dev.brighten.ac.Anticheat;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.BlockUtils;
import dev.brighten.ac.utils.LongHash;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.Materials;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.types.RayCollision;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
@Slf4j
@SuppressWarnings("unused")
@RequiredArgsConstructor
public class BlockUpdateHandler {
private final Long2ObjectOpenHashMap<KColumn> chunks = new Long2ObjectOpenHashMap<>(1000);
private final APlayer player;
private final Map<String, World> worlds = new HashMap<>();
@Getter
private AtomicReference<World> currentWorld;
/**
* Clear all chunks when the player changes worlds
*/
public void onWorldChange() {
synchronized (chunks) {
chunks.clear();
}
public void onRespawn(WrapperPlayServerRespawn respawn) {
respawn.getWorldName()
.filter(name -> !name.equals(currentWorld.get().getName()))
.ifPresent(worldName -> {
currentWorld.set(getWorldByName(worldName));
player.getMob().despawn();
setMinHeight(player.getDimensionType());
player.runKeepaliveAction(ka -> {
KLocation origin = player.getMovement().getTo().getLoc().add(0, 1.7, 0);
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1));
Vector3d loc1 = coll.collisionPoint(1.2);
player.getMob().spawn(true, new KLocation(loc1), new ArrayList<>(), player);
}, 1);
});
}
private World getWorldByName(String name) {
return worlds.values().stream()
.filter(world -> world.getName().equals(name))
.findFirst()
.orElse(worlds.put(name, new World(name)));
}
/**
@@ -68,25 +73,29 @@ public class BlockUpdateHandler {
public void onPlace(WrapperPlayClientPlayerBlockPlacement place) {
player.getInfo().lastBlockUpdate.reset();
// Could not possibly be a block placement as it's not a block a player is holding.
IntVector pos = new IntVector(place.getBlockPosition());
Vector3i pos = place.getBlockPosition();
// Some dumbass shit I have to do because Minecraft with Lilypads
if (place.getItemStack().isPresent()
&& BlockUtils.getXMaterial(place.getItemStack().get().getType()).equals(XMaterial.LILY_PAD)) {
RayCollision rayCollision = new RayCollision(player.getBukkitPlayer().getEyeLocation().toVector(),
player.getBukkitPlayer().getLocation().getDirection());
&& place.getItemStack().get().getType().equals(ItemTypes.LILY_PAD)) {
RayCollision rayCollision = new RayCollision(player.getMovement().getTo().getLoc()
.add(0, player.getEyeHeight(), 0).toVector(),
player.getMovement().getTo().getLoc().getDirection());
WrappedBlock block = rayCollision.getClosestBlockOfType(player, Materials.LIQUID, 5);
if (block != null) {
pos = new IntVector(block.getLocation().getX(), block.getLocation().getY() + 1, block.getLocation().getZ());
pos = new Vector3i(
block.getLocation().getX(),
block.getLocation().getY() + 1,
block.getLocation().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.getFace().getModX());
pos.setY(pos.getY() + place.getFace().getModY());
pos.setZ(pos.getZ() + place.getFace().getModZ());
pos = pos.with(pos.getX() + place.getFace().getModX(),
pos.getY() + place.getFace().getModY(),
pos.getZ() + place.getFace().getModZ());
}
player.getInfo().getLastPlace().reset();
@@ -96,207 +105,16 @@ public class BlockUpdateHandler {
int y = pos.getY();
int z = pos.getZ();
var placedType = place.getItemStack().get().getType().getPlacedType();
if(place.getItemStack().isEmpty() || placedType == null) {
if(place.getItemStack().isEmpty() || place.getItemStack().get().getType().getPlacedType() == null) {
return;
}
updateBlock(x, y, z, WrappedBlockState.getDefaultState(placedType));
currentWorld.get().updateBlock(x, y, z,
WrappedBlockState.getDefaultState(place.getItemStack().get().getType().getPlacedType()));
}
/**
* Keep track of block diggings since the Bukkit API will be a bit behind
* @param x x coordinate
* @param z z coordinate
* @return the chunk at the specified coordinates
*/
public KColumn getChunk(int x, int z) {
synchronized (chunks) {
long hash = LongHash.toLong(x >> 4, z >> 4);
KColumn chunk = chunks.get(hash);
// If the chunk is null, create a new one
if(chunk == null) {
chunk = getBukkitColumn(player.getBukkitPlayer().getWorld(), x, z);
if(chunk == null) {
return new KColumn(x, z, new BaseChunk[maxHeight / 16]);
}
chunks.put(hash, chunk);
}
return chunk;
}
}
private KColumn getBukkitColumn(World world, int x, int z) {
Chunk chunk = BlockUtils.getChunkAsync(world, x >> 4, z >> 4).orElse(null);
if(chunk == null) {
// Handle loading on main thread
Anticheat.INSTANCE.getRunUtils().task(() -> {
long hash = LongHash.toLong(x >> 4, z >> 4);
if(!chunks.containsKey(hash)) {
chunks.put(hash, getBukkitColumn(world, x, z));
}
});
return null;
}
BaseChunk[] levels = new BaseChunk[world.getMaxHeight() / 16];
for(int i = 0; i < levels.length; i++) {
levels[i] = create();
}
int chunkX = chunk.getX() * 16;
int chunkZ = chunk.getZ() * 16;
for(int blockX = chunkX; blockX < chunkX + 16 ; blockX++) {
for(int blockZ = chunkZ; blockZ < chunkZ + 16 ; blockZ++) {
for(int blockY = minHeight ; blockY < world.getMaxHeight() ; blockY++) {
Block block = chunk.getBlock(blockX, blockY, blockZ);
if(block.getType() == null || block.getType().equals(Material.AIR)) {
continue; // Air
}
BaseChunk baseChunk = levels[blockY >> 4];
WrappedBlockState state = SpigotConversionUtil.fromBukkitMaterialData(block.getState().getData());
baseChunk.set(blockX & 15, blockY & 15, blockZ & 15, state);
}
}
}
return new KColumn(x, z, levels);
}
private void updateChunk(Column chunk) {
synchronized (chunks) {
KColumn column = new KColumn(chunk.getX(), chunk.getZ(), chunk.getChunks());
chunks.put(LongHash.toLong(column.x(), column.z()), column);
}
}
private static BaseChunk create() {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_18)) {
return new Chunk_v1_18();
} else if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) {
return new Chunk_v1_9(0, PaletteType.BIOME.create().paletteType.create());
} else if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_8)) {
return new Chunk_v1_8(false);
}
return new Chunk_v1_7(false, false);
}
/**
* Get a block at the specified coordinates
* @param location the location of the block
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(Location location) {
return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
private int minHeight = 0, maxHeight = 256;
public void setMinHeight(DimensionType type) {
minHeight = type.getMinY();
maxHeight = minHeight + type.getHeight();
}
private static final WrappedBlockState airBlockState = WrappedBlockState.getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), 0);
/**
* Get a block at the specified coordinates
* @param x x coordinate
* @param y y coordinate
* @param z z coordinate
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(int x, int y, int z) {
KColumn col = getChunk(x, z);
y -= minHeight;
final int worldY = y;
// Fast bounds check for absurd/invalid Y before chunk indexing
if (y < 0 || y >= (maxHeight - minHeight)) {
return new WrappedBlock(new IntVector(x, worldY, z),
StateTypes.AIR,
airBlockState);
}
// Also ensure the section index is within the cached column bounds
final int sectionIndex = y >> 4;
if (sectionIndex >= col.chunks().length) {
return new WrappedBlock(new IntVector(x, worldY, z),
StateTypes.AIR,
airBlockState);
}
BaseChunk chunk = col.chunks()[sectionIndex];
if(chunk == null) {
//Get Bukkit Block
Block block = BlockUtils.getBlockAsync(new Location(player.getBukkitPlayer().getWorld(), x, y, z))
.orElse(null);
if(block != null) {
WrappedBlockState state = SpigotConversionUtil.fromBukkitMaterialData(block.getState().getData());
if (state.getType() == StateTypes.AIR) {
return new WrappedBlock(new IntVector(x, y + minHeight, z),
StateTypes.AIR,
airBlockState);
} else {
chunk = create();
col.chunks()[y >> 4] = chunk;
chunk.set(x & 15, y & 15, z & 15, state);
}
} else return new WrappedBlock(new IntVector(x, y, z),
StateTypes.AIR,
airBlockState);
}
WrappedBlockState state = chunk.get(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(),x & 15, y & 15, z & 15);
return new WrappedBlock(new IntVector(x, y, z),
state.getType(),
state);
}
/**
* Get a block at the specified coordinates
* @param vec the coordinates
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(IntVector vec) {
return getBlock(vec.getX(), vec.getY(), vec.getZ());
}
public WrappedBlock getBlock(Vector3d vec) {
return getBlock(
MathHelper.floor_double(vec.getX()),
MathHelper.floor_double(vec.getY()),
MathHelper.floor_double(vec.getZ())
);
}
/**
* Get a block at the specified coordinates
* @param block Grabs coordinates from @link{org.bukkit.block.Block}
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(Block block) {
return getBlock(block.getX(), block.getY(), block.getZ());
}
static final WrappedBlockState airBlockState = WrappedBlockState
.getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), 0);
/**
* Keep track of block breaking since the Bukkit API will be a bit behind.
@@ -307,13 +125,13 @@ public class BlockUpdateHandler {
player.getInfo().lastBlockUpdate.reset();
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) {
IntVector pos = new IntVector(dig.getBlockPosition());
Vector3i pos = dig.getBlockPosition();
if (pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) {
return;
}
updateBlock(pos.getX(), pos.getY(), pos.getZ(), airBlockState);
currentWorld.get().updateBlock(pos.getX(), pos.getY(), pos.getZ(), airBlockState);
}
}
@@ -326,9 +144,9 @@ public class BlockUpdateHandler {
// Updating block information
player.runKeepaliveAction(k -> {
IntVector pos = new IntVector(packet.getBlockPosition());
Vector3i pos = packet.getBlockPosition();
updateBlock(pos.getX(), pos.getY(), pos.getZ(), packet.getBlockState());
currentWorld.get().updateBlock(pos.getX(), pos.getY(), pos.getZ(), packet.getBlockState());
});
}
@@ -341,41 +159,20 @@ public class BlockUpdateHandler {
player.runKeepaliveAction(k -> {
for (WrapperPlayServerMultiBlockChange.EncodedBlock info : packet.getBlocks()) {
WrappedBlockState blockState = info.getBlockState(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
WrappedBlockState blockState = info
.getBlockState(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
updateBlock(info.getX(), info.getY(), info.getZ(), blockState);
currentWorld.get().updateBlock(info.getX(), info.getY(), info.getZ(), blockState);
}
});
}
private void updateBlock(int x, int y, int z, WrappedBlockState blockState) {
KColumn col = getChunk(x, z);
int offset = y - minHeight;
if(offset < 0 || (offset >> 4) > col.chunks().length) {
return;
}
BaseChunk chunk = col.chunks()[offset >> 4];
if(chunk == null) {
chunk = create();
col.chunks()[offset >> 4] = chunk;
chunk.set(player.getPlayerVersion(), 0, 0, 0, 0);
}
chunk.set(x & 15, offset & 15, z & 15,
blockState);
}
/**
* Keep track of block updates since the Bukkit API will be a bit behind.
* @param chunkUpdate Wrapped PacketPlayOutMapChunk
*/
public void runUpdate(WrapperPlayServerChunkData chunkUpdate) {
player.runKeepaliveAction(k -> updateChunk(chunkUpdate.getColumn()));
player.runKeepaliveAction(k -> currentWorld.get().updateChunk(chunkUpdate.getColumn()));
}
public void runUpdate(WrapperPlayServerChunkDataBulk chunkBulk) {
@@ -386,9 +183,10 @@ public class BlockUpdateHandler {
int x = chunkBulk.getX()[index];
int z = chunkBulk.getZ()[index];
Column column = new Column(x, z, true, chunks, new TileEntity[0], chunkBulk.getBiomeData()[index]);
Column column = new Column(x, z, true, chunks, new TileEntity[0],
chunkBulk.getBiomeData()[index]);
updateChunk(column);
currentWorld.get().updateChunk(column);
}
});
}
@@ -401,8 +199,8 @@ public class BlockUpdateHandler {
* @param modZ the z modifier
* @return the block relative to the specified location
*/
public WrappedBlock getRelative(IntVector location, int modX, int modY, int modZ) {
return getBlock(location.clone().add(modX, modY, modZ));
public WrappedBlock getRelative(Vector3i location, int modX, int modY, int modZ) {
return currentWorld.get().getBlock(location.add(modX, modY, modZ));
}
/**
@@ -412,7 +210,7 @@ public class BlockUpdateHandler {
* @param distance the distance
* @return the block relative to the specified location
*/
public WrappedBlock getRelative(IntVector location, BlockFace face, int distance) {
public WrappedBlock getRelative(Vector3i location, BlockFace face, int distance) {
return getRelative(location,
face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance);
}
@@ -423,8 +221,20 @@ public class BlockUpdateHandler {
* @param face the face
* @return the block relative to the specified location
*/
public WrappedBlock getRelative(IntVector location, BlockFace face) {
return getBlock(location.clone().add(face.getModX(), face.getModY(), face.getModZ()));
public WrappedBlock getRelative(Vector3i location, BlockFace face) {
return currentWorld.get().getBlock(location.add(face.getModX(), face.getModY(), face.getModZ()));
}
public WrappedBlock getBlock(int x, int y, int z) {
return currentWorld.get().getBlock(x, y, z);
}
public WrappedBlock getBlock(KLocation location) {
return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
public WrappedBlock getBlock(Vector3i location) {
return getBlock(location.getX(), location.getY(), location.getZ());
}
public record KColumn(int x, int z, BaseChunk[] chunks) {}
@@ -1,9 +1,11 @@
package dev.brighten.ac.handler.block;
import dev.brighten.ac.utils.math.IntVector;
import com.github.retrooper.packetevents.util.Vector3i;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
@RequiredArgsConstructor
@@ -17,7 +19,7 @@ public class Chunk {
* @param location - Location of the block
* @return Optional of the block at the specified location
*/
public Optional<WrappedBlock> getBlockAt(IntVector location) {
public Optional<WrappedBlock> getBlockAt(Vector3i location) {
return getBlockAt(location.getX(), location.getY(), location.getZ());
}
@@ -64,7 +66,18 @@ public class Chunk {
* @param location - Location of the block
* @param block - Block to update to
*/
public void updateBlock(IntVector location, WrappedBlock block) {
public void updateBlock(Vector3i location, WrappedBlock block) {
updateBlock(location.getX(), location.getY(), location.getZ(), block);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Chunk chunk)) return false;
return x == chunk.x && z == chunk.z && Objects.deepEquals(blocks, chunk.blocks);
}
@Override
public int hashCode() {
return Objects.hash(x, z, Arrays.deepHashCode(blocks));
}
}
@@ -0,0 +1,169 @@
package dev.brighten.ac.handler.block;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.Column;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_16.Chunk_v1_9;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_7.Chunk_v1_7;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_8.Chunk_v1_8;
import com.github.retrooper.packetevents.protocol.world.chunk.impl.v_1_18.Chunk_v1_18;
import com.github.retrooper.packetevents.protocol.world.chunk.palette.PaletteType;
import com.github.retrooper.packetevents.protocol.world.dimension.DimensionType;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.LongHash;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import lombok.Getter;
import me.hydro.emulator.util.mcp.MathHelper;
import java.util.Map;
import java.util.Optional;
@Getter
public class World {
private final String name;
private final Long2ObjectOpenHashMap<BlockUpdateHandler.KColumn> chunks = new Long2ObjectOpenHashMap<>(1000);
private final Map<Integer, TrackedEntity> trackedEntities = new Int2ObjectOpenHashMap<>();
public World(String name) {
this.name = name;
}
private int minHeight = 0, maxHeight = 256;
public void setMinHeight(DimensionType type) {
minHeight = type.getMinY();
maxHeight = minHeight + type.getHeight();
}
/**
* Keep track of block diggings since the Bukkit API will be a bit behind
* @param x x coordinate
* @param z z coordinate
* @return the chunk at the specified coordinates
*/
public BlockUpdateHandler.KColumn getChunk(int x, int z) {
synchronized (chunks) {
long hash = LongHash.toLong(x >> 4, z >> 4);
BlockUpdateHandler.KColumn chunk = chunks.get(hash);
// If the chunk is null, create a new one
if(chunk == null) {
return chunks.put(hash, new BlockUpdateHandler.KColumn(x, z, new BaseChunk[maxHeight / 16]));
}
return chunk;
}
}
void updateChunk(Column chunk) {
synchronized (chunks) {
BlockUpdateHandler.KColumn column = new BlockUpdateHandler.KColumn(chunk.getX(), chunk.getZ(), chunk.getChunks());
chunks.put(LongHash.toLong(column.x(), column.z()), column);
}
}
private static BaseChunk create() {
if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_18)) {
return new Chunk_v1_18();
} else if (PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9)) {
return new Chunk_v1_9(0, PaletteType.BIOME.create().paletteType.create());
} else if(PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_8)) {
return new Chunk_v1_8(false);
}
return new Chunk_v1_7(false, false);
}
/**
* Get a block at the specified coordinates
* @param location the location of the block
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(KLocation location) {
return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
/**
* Get a block at the specified coordinates
* @param x x coordinate
* @param y y coordinate
* @param z z coordinate
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(int x, int y, int z) {
BlockUpdateHandler.KColumn col = getChunk(x, z);
y -= minHeight;
BaseChunk chunk = col.chunks().length - 1 < (y >> 4) ? null : col.chunks()[y >> 4];
if(chunk == null) {
//Get Bukkit Block
return new WrappedBlock(new Vector3i(x, y, z),
StateTypes.AIR,
BlockUpdateHandler.airBlockState);
}
WrappedBlockState state = chunk.get(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(),x & 15, y & 15, z & 15);
return new WrappedBlock(new Vector3i(x, y, z),
state.getType(),
state);
}
void updateBlock(int x, int y, int z, WrappedBlockState blockState) {
BlockUpdateHandler.KColumn col = getChunk(x, z);
int offset = y - minHeight;
if(offset < 0 || (offset >> 4) > col.chunks().length) {
return;
}
BaseChunk chunk = col.chunks()[offset >> 4];
if(chunk == null) {
chunk = create();
col.chunks()[offset >> 4] = chunk;
chunk.set(null, 0, 0, 0, 0);
}
chunk.set(x & 15, offset & 15, z & 15,
blockState);
}
/**
* Get a block at the specified coordinates
* @param vec the coordinates
* @return the block at the specified coordinates
*/
public WrappedBlock getBlock(Vector3i vec) {
return getBlock(vec.getX(), vec.getY(), vec.getZ());
}
public WrappedBlock getBlock(Vector3d vec) {
return getBlock(
MathHelper.floor_double(vec.getX()),
MathHelper.floor_double(vec.getY()),
MathHelper.floor_double(vec.getZ())
);
}
public Optional<TrackedEntity> getTrackedEntity(int entityId) {
TrackedEntity trackedEntity = trackedEntities.get(entityId);
if(trackedEntity == null) {
return Optional.empty();
}
return Optional.of(trackedEntity);
}
}
@@ -2,14 +2,14 @@ package dev.brighten.ac.handler.block;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import dev.brighten.ac.utils.math.IntVector;
import com.github.retrooper.packetevents.util.Vector3i;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class WrappedBlock {
private IntVector location;
private Vector3i location;
private StateType type;
private WrappedBlockState blockState;
}
@@ -1,13 +1,19 @@
package dev.brighten.ac.handler.entity;
import com.github.retrooper.packetevents.protocol.attribute.Attribute;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes;
import dev.brighten.ac.data.obj.Pose;
import dev.brighten.ac.handler.ValuedAttribute;
import dev.brighten.ac.utils.EntityLocation;
import dev.brighten.ac.utils.KLocation;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Getter
@Setter
@@ -17,6 +23,8 @@ public class TrackedEntity {
private KLocation location;
private EntityLocation oldEntityLocation, newEntityLocation;
private List<FakeMob> fakeMobs = new ArrayList<>();
private Set<ValuedAttribute> attributes = new HashSet<>();
private Pose pose = Pose.STANDING;
public TrackedEntity(int entityId, EntityType entityType, KLocation location) {
this.entityId = entityId;
@@ -31,4 +39,30 @@ public class TrackedEntity {
newEntityLocation.yaw = location.getYaw();
newEntityLocation.pitch = location.getPitch();
}
public KLocation getEyeLocation() {
return new KLocation(location.getX(), location.getY() + pose.eyeHeight, location.getZ(),
location.getYaw(), location.getPitch());
}
public ValuedAttribute getAttribute(Attribute type) {
for(ValuedAttribute attribute : attributes) {
if(attribute.getAttribute().equals(type)) {
return attribute;
}
}
return null;
}
public void updateAttribute(WrapperPlayServerUpdateAttributes.Property property) {
ValuedAttribute attribute = getAttribute(property.getAttribute());
if(attribute == null) {
attribute = new ValuedAttribute(property.getAttribute());
}
attribute.updateAttribute(property);
attributes.add(attribute);
}
}
@@ -49,7 +49,7 @@ public class KeepaliveProcessor {
double dh = Math.min(value.getMovement().getDeltaXZ(), 1),
dy = Math.min(1, Math.abs(value.getMovement().getDeltaY()));
value.getInfo().nearbyEntities = value.getEntityLocationHandler().getTrackedEntities().values()
value.getInfo().nearbyEntities = value.getWorldTracker().getCurrentWorld().get().getTrackedEntities().values()
.stream()
.filter(te ->
te.getLocation().distance(value.getMovement().getTo().getLoc()) < (2 + (dh + dy) / 2))
@@ -1,25 +1,8 @@
package dev.brighten.ac.handler.protocol;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.handler.protocol.impl.NoAPI;
import dev.brighten.ac.handler.protocol.impl.ProtocolSupport;
import dev.brighten.ac.handler.protocol.impl.ViaVersionAPI;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import dev.brighten.ac.data.APlayer;
public interface Protocol {
int getPlayerVersion(Player player);
static Protocol getProtocol() {
if(Bukkit.getPluginManager().isPluginEnabled("ViaVersion")) {
Anticheat.INSTANCE.alog("Using ViaVersion for ProtocolAPI");
return new ViaVersionAPI();
} else if(Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport")) {
Anticheat.INSTANCE.alog("Using ProtocolSupport for ProtocolAPI");
return new ProtocolSupport();
} else {
Anticheat.INSTANCE.alog("Using Vanilla API for ProtocolAPI");
return new NoAPI();
}
}
int getPlayerVersion(APlayer player);
}
@@ -1,13 +1,13 @@
package dev.brighten.ac.handler.protocol.impl;
import com.github.retrooper.packetevents.PacketEvents;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.protocol.Protocol;
import org.bukkit.entity.Player;
public class NoAPI implements Protocol {
@Override
public int getPlayerVersion(Player player) {
public int getPlayerVersion(APlayer player) {
return PacketEvents.getAPI().getPlayerManager().getClientVersion(player).getProtocolVersion();
}
}
@@ -1,13 +0,0 @@
package dev.brighten.ac.handler.protocol.impl;
import dev.brighten.ac.handler.protocol.Protocol;
import org.bukkit.entity.Player;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupport implements Protocol {
@Override
public int getPlayerVersion(Player player) {
return ProtocolSupportAPI.getProtocolVersion(player).getId();
}
}
@@ -2,16 +2,16 @@ package dev.brighten.ac.handler.protocol.impl;
import com.viaversion.viaversion.api.Via;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.protocol.Protocol;
import org.bukkit.entity.Player;
public class ViaVersionAPI implements Protocol {
@Override
public int getPlayerVersion(Player player) {
Anticheat.INSTANCE.alog("Getting player version for " + player.getName());
var toReturn = Via.getAPI().getPlayerVersion(player.getUniqueId());
Anticheat.INSTANCE.alog("Player version for " + player.getName() + " is " + toReturn);
public int getPlayerVersion(APlayer player) {
Anticheat.INSTANCE.alog("Getting player version for " + player.getBukkitPlayer().getName());
var toReturn = Via.getAPI().getPlayerVersion(player.getBukkitPlayer().getUniqueId());
Anticheat.INSTANCE.alog("Player version for " + player.getBukkitPlayer().getName() + " is " + toReturn);
return toReturn;
}
@@ -1,5 +1,6 @@
package dev.brighten.ac.listener;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.KLocation;
@@ -68,14 +69,15 @@ public class GeneralListener implements Listener {
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId())
.ifPresent(player -> {
player.getBlockUpdateHandler().onWorldChange();
// Updating bot loc when changing worlds
Location origin = event.getTo().clone().add(0, 1.7, 0);
Vector mult = origin.getDirection().multiply(-1);
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1));
RayCollision coll = new RayCollision(new Vector3d(origin.getX(), origin.getY(), origin.getZ()),
new Vector3d(mult.getX(), mult.getY(), mult.getZ()));
Vector loc1 = coll.collisionPoint(1.2);
Vector3d loc1 = coll.collisionPoint(1.2);
Anticheat.INSTANCE.getRunUtils().taskLater(() -> {
player.getMob().despawn();
@@ -1,6 +1,7 @@
package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.protocol.world.Direction;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.utils.world.types.RayCollision;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location;
@@ -211,6 +212,14 @@ public class AxisAlignedBB {
return rayTrace(origin, dir);
}
public Vec3D rayTrace(Vector3d vorigin, Vector3d vdirection, double distance) {
Vec3D origin = new Vec3D(vorigin.getX(), vorigin.getY(), vorigin.getZ());
Vector3d direction = vdirection.multiply(distance);
Vec3D dir = origin.clone().add(direction.getX(), direction.getY(), direction.getZ());
return rayTrace(origin, dir);
}
public Vec3D rayTrace(Vec3D vec3d, Vec3D vec3d1) {
Vec3D vec3d2 = vec3d.a(vec3d1, this.minX);
Vec3D vec3d3 = vec3d.a(vec3d1, this.maxX);
@@ -2,19 +2,18 @@ package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.utils.math.IntVector;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Vehicle;
import java.util.EnumMap;
import java.util.EnumSet;
@@ -84,20 +83,20 @@ public class BlockUtils {
return Optional.empty();
}
public static Optional<WrappedBlock> getRelative(APlayer player, IntVector location, int modX, int modY, int modZ) {
return Optional.of(player.getBlockUpdateHandler()
.getRelative(new IntVector(location.getX(), location.getY(), location.getZ()),
public static Optional<WrappedBlock> getRelative(APlayer player, Vector3i location, int modX, int modY, int modZ) {
return Optional.of(player.getWorldTracker()
.getRelative(new Vector3i(location.getX(), location.getY(), location.getZ()),
modX, modY, modZ));
}
public static Optional<WrappedBlock> getRelative(APlayer player, IntVector location,
public static Optional<WrappedBlock> getRelative(APlayer player, Vector3i location,
com.github.retrooper.packetevents.protocol.world
.BlockFace face, int distance) {
return getRelative(player, location,
face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance);
}
public static Optional<WrappedBlock> getRelative(APlayer player, IntVector vector, BlockFace face) {
public static Optional<WrappedBlock> getRelative(APlayer player, Vector3i vector, BlockFace face) {
return getRelative(player, vector,
face.getModX(), face.getModY(), face.getModZ());
}
@@ -134,6 +133,12 @@ public class BlockUtils {
return isUsable(getXMaterial(material));
}
public static boolean isUsable(ClientVersion version, ItemType type) {
return type.hasAttribute(ItemTypes.ItemAttribute.EDIBLE)
|| (version.isOlderThan(ClientVersion.V_1_9) && type.hasAttribute(ItemTypes.ItemAttribute.SWORD))
|| type.equals(ItemTypes.SHIELD);
}
public static boolean isUsable(XMaterial xmaterial) {
if(XEDIBLE.contains(xmaterial)) return true;
return switch (xmaterial) {
@@ -1,16 +1,15 @@
package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.particle.Particle;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3f;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerParticle;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.EntityData;
@@ -137,8 +136,8 @@ public class Helper {
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);
StateType type = player.getBlockUpdateHandler().getBlock(vec).getType();
Vector3i vec = new Vector3i(x, y, z);
StateType type = player.getWorldTracker().getBlock(vec).getType();
if (type != StateTypes.AIR && (mask == -100 || Materials.checkFlag(type, mask))) {
CollisionBox box = BlockData.getData(type)
@@ -0,0 +1,7 @@
package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.protocol.potion.PotionType;
public record KPotionEffect(PotionType potionType, KProperties properties) {
}
@@ -0,0 +1,18 @@
package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
import org.jetbrains.annotations.Nullable;
public record KProperties(int amplifier, int duration, boolean ambient, boolean showParticles, boolean showIcon,
@Nullable KProperties hiddenEffect) {
public PotionEffect.Properties toProperties() {
return new PotionEffect.Properties(amplifier, duration, ambient, showParticles, showIcon,
hiddenEffect == null ? null : hiddenEffect.toProperties());
}
public static KProperties fromBukkit(org.bukkit.potion.PotionEffect potionEffect) {
return new KProperties(potionEffect.getAmplifier(), potionEffect.getDuration(), potionEffect.isAmbient(),
potionEffect.hasParticles(), false, null);
}
}
@@ -58,7 +58,7 @@ public class MiscUtils {
for(int x = startX ; x < endX ; x++) {
for(int y = startY ; y < endY ; y++) {
for(int z = startZ ; z < endZ ; z++) {
StateType type = player.getBlockUpdateHandler().getBlock(x, y, z).getType();
StateType type = player.getWorldTracker().getBlock(x, y, z).getType();
if(Materials.checkFlag(type, bitmask))
return true;
@@ -19,7 +19,7 @@ public class MovementUtils {
public static double getJumpHeight(APlayer data) {
float baseHeight = 0.42f;
baseHeight+= data.getInfo().groundJumpBoost.map(ef -> ef.getAmplifier() + 1)
baseHeight+= data.getInfo().groundJumpBoost.map(ef -> ef.properties().amplifier() + 1)
.orElse(0) * 0.1f;
return baseHeight;
@@ -38,7 +38,7 @@ public class MovementUtils {
int i = MathHelper.floor_double(data.getMovement().getTo().getLoc().getX());
int j = MathHelper.floor_double(data.getMovement().getTo().getBox().minY);
int k = MathHelper.floor_double(data.getMovement().getTo().getLoc().getZ());
WrappedBlock block = data.getBlockUpdateHandler().getBlock(i, j, k);
WrappedBlock block = data.getWorldTracker().getBlock(i, j, k);
return Materials.checkFlag(block.getType(), Materials.LADDER);
@@ -54,6 +54,10 @@ public class IntVector implements Cloneable {
return new Vector(x, y, z);
}
public Vector3i toVector3i() {
return new Vector3i(x, y, z);
}
@Override
public String toString() {
return "[" + x + ", " + y + ", " + z + "]";
@@ -2,11 +2,14 @@ package dev.brighten.ac.utils.math;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
@@ -15,15 +18,15 @@ public class RayTrace {
//origin = start position
//direction = direction in which the raytrace will go
Vector origin, direction;
Vector3d origin, direction;
public RayTrace(Vector origin, Vector direction) {
public RayTrace(Vector3d origin, Vector3d direction) {
this.origin = origin;
this.direction = direction;
}
//general intersection detection
public static boolean intersects(Vector position, Vector min, Vector max) {
public static boolean intersects(Vector3d position, Vector3d min, Vector3d max) {
if (position.getX() < min.getX() || position.getX() > max.getX()) {
return false;
} else if (position.getY() < min.getY() || position.getY() > max.getY()) {
@@ -32,27 +35,27 @@ public class RayTrace {
}
//get a point on the raytrace at X blocks away
public Vector getPostion(double blocksAway) {
return origin.clone().add(direction.clone().multiply(blocksAway));
public Vector3d getPostion(double blocksAway) {
return origin.add(direction.multiply(blocksAway));
}
//checks if a position is on contained within the position
public boolean isOnLine(Vector position) {
public boolean isOnLine(Vector3d position) {
double t = (position.getX() - origin.getX()) / direction.getX();
return position.getBlockY() == origin.getY() + (t * direction.getY()) && position.getBlockZ() == origin.getZ() + (t * direction.getZ());
return MathUtils.floor(position.getY()) == origin.getY() + (t * direction.getY()) && MathUtils.floor(position.getZ()) == origin.getZ() + (t * direction.getZ());
}
//get all postions on a raytrace
public List<Vector> traverse(double blocksAway, double accuracy) {
List<Vector> positions = new ArrayList<>();
public List<Vector3d> traverse(double blocksAway, double accuracy) {
List<Vector3d> positions = new ArrayList<>();
for (double d = 0; d <= blocksAway; d += accuracy) {
positions.add(getPostion(d));
}
return positions;
}
public List<Vector> traverse(double skip, double blocksAway, double accuracy) {
List<Vector> positions = new ArrayList<>();
public List<Vector3d> traverse(double skip, double blocksAway, double accuracy) {
List<Vector3d> positions = new ArrayList<>();
for (double d = skip; d <= blocksAway; d += accuracy) {
positions.add(getPostion(d));
}
@@ -62,14 +65,17 @@ public class RayTrace {
public List<Block> getBlocks(World world, double blocksAway, double accuracy) {
List<Block> blocks = new ArrayList<>();
traverse(blocksAway, accuracy).stream().filter(vector -> vector.toLocation(world).getBlock().getType().isSolid()).forEach(vector -> blocks.add(vector.toLocation(world).getBlock()));
traverse(blocksAway, accuracy).stream()
.map(KLocation::new)
.filter(vector -> vector.toLocation(world).getBlock().getType().isSolid())
.forEach(vector -> blocks.add(vector.toLocation(world).getBlock()));
return blocks;
}
//intersection detection for current raytrace with return
public Vector positionOfIntersection(Vector min, Vector max, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
public Vector3d positionOfIntersection(Vector3d min, Vector3d max, double blocksAway, double accuracy) {
List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector3d position : positions) {
if (intersects(position, min, max)) {
return position;
}
@@ -78,9 +84,9 @@ public class RayTrace {
}
//intersection detection for current raytrace
public boolean intersects(Vector min, Vector max, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
public boolean intersects(Vector3d min, Vector3d max, double blocksAway, double accuracy) {
List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector3d position : positions) {
if (intersects(position, min, max)) {
return true;
}
@@ -89,9 +95,9 @@ public class RayTrace {
}
//bounding blockbox instead of vector
public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
public Vector3d positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return position;
}
@@ -99,9 +105,9 @@ public class RayTrace {
return null;
}
public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector> positions = traverse(skip, blocksAway, accuracy);
for (Vector position : positions) {
public Vector3d positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector3d> positions = traverse(skip, blocksAway, accuracy);
for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return position;
}
@@ -111,8 +117,8 @@ public class RayTrace {
//bounding blockbox instead of vector
public boolean intersects(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return true;
}
@@ -121,8 +127,8 @@ public class RayTrace {
}
public boolean intersects(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) {
List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) {
return true;
}
@@ -132,8 +138,8 @@ public class RayTrace {
//debug / effects
public void highlight(World world, double blocksAway, double accuracy) {
for (Vector position : traverse(blocksAway, accuracy)) {
world.playEffect(position.toLocation(world), (PacketEvents.getAPI().getServerManager().getVersion()
for (Vector3d position : traverse(blocksAway, accuracy)) {
world.playEffect(new Location(world, position.x, position.y, position.z), (PacketEvents.getAPI().getServerManager().getVersion()
.isNewerThanOrEquals(ServerVersion.V_1_13) ? Effect.SMOKE : Effect.valueOf("COLOURED_DUST")), 0);
}
}
@@ -8,10 +8,10 @@ import com.github.retrooper.packetevents.protocol.world.states.defaulttags.Block
import com.github.retrooper.packetevents.protocol.world.states.enums.*;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.BlockUtils;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.blocks.*;
import dev.brighten.ac.utils.world.types.*;
@@ -361,10 +361,10 @@ public enum BlockData {
return getBox(player, block.getLocation(), version);
}
public CollisionBox getBox(APlayer player, IntVector block, ClientVersion version) {
public CollisionBox getBox(APlayer player, Vector3i block, ClientVersion version) {
if (this.box != null)
return this.box.copy().offset(block.getX(), block.getY(), block.getZ());
return new DynamicCollisionBox(dynamic, player, player.getBlockUpdateHandler().getBlock(block), version)
return new DynamicCollisionBox(dynamic, player, player.getWorldTracker().getBlock(block), version)
.offset(block.getX(), block.getY(), block.getZ());
}
@@ -3,6 +3,7 @@ package dev.brighten.ac.utils.world;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.world.types.NoCollisionBox;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location;
@@ -23,6 +24,10 @@ public class EntityData {
return bounds(entity.getEntityType()).offset(location.getX(), location.getY(), location.getZ());
}
public static CollisionBox getEntityBox(KLocation location, TrackedEntity entity) {
return bounds(entity.getEntityType()).offset(location.getX(), location.getY(), location.getZ());
}
public static CollisionBox getEntityBox(Location location, EntityType entity) {
return bounds(entity).offset(location.getX(), location.getY(), location.getZ());
}
@@ -7,9 +7,9 @@ import com.github.retrooper.packetevents.protocol.world.BlockFace;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.enums.Half;
import com.github.retrooper.packetevents.protocol.world.states.enums.Hinge;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.types.CollisionFactory;
import dev.brighten.ac.utils.world.types.HexCollisionBox;
@@ -50,10 +50,10 @@ public class DoorHandler implements CollisionFactory {
if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2)
|| version.isOlderThanOrEquals(ClientVersion.V_1_12_2)) {
if (door.getBlockState().getHalf() == Half.LOWER) {
IntVector aboveVec = door.getLocation().clone();
Vector3i aboveVec = door.getLocation();
aboveVec.setY(aboveVec.getY() + 1);
WrappedBlockState above = player.getBlockUpdateHandler().getBlock(aboveVec).getBlockState();
aboveVec = aboveVec.add(0, aboveVec.getY() + 1, 0);
WrappedBlockState above = player.getWorldTracker().getBlock(aboveVec).getBlockState();
facingDirection = door.getBlockState().getFacing();
isClosed = !door.getBlockState().isOpen();
@@ -67,10 +67,10 @@ public class DoorHandler implements CollisionFactory {
isRightHinge = false;
}
} else {
IntVector belowVec = door.getLocation().clone();
Vector3i belowVec = door.getLocation();
belowVec.setY(belowVec.getY() - 1);
WrappedBlockState below = player.getBlockUpdateHandler().getBlock(belowVec).getBlockState();
belowVec = belowVec.add(0, belowVec.getY() - 1, 0);
WrappedBlockState below = player.getWorldTracker().getBlock(belowVec).getBlockState();
if (below.getType() == door.getBlockState().getType() && below.getHalf() == Half.LOWER) {
isClosed = !below.isOpen();
@@ -44,7 +44,7 @@ public class DynamicStair implements CollisionFactory {
z = originalStairs.getLocation().getZ();
WrappedBlock offsetOne = player == null
? null
: player.getBlockUpdateHandler().getBlock(
: player.getWorldTracker().getBlock(
x + facing.getModX(),
y + facing.getModY(),
z + facing.getModZ());
@@ -64,7 +64,7 @@ public class DynamicStair implements CollisionFactory {
}
}
WrappedBlock offsetTwo = player.getBlockUpdateHandler()
WrappedBlock offsetTwo = player.getWorldTracker()
.getBlock(x + facing.getOppositeFace().getModX(),
y + facing.getOppositeFace().getModY(), z
+ facing.getOppositeFace().getModZ());
@@ -4,18 +4,18 @@ import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.utils.Helper;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.Materials;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.math.RayTrace;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.CollisionBox;
import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,15 +58,15 @@ public class RayCollision implements CollisionBox {
directionZ = 0;
}
public RayCollision(LivingEntity e) {
public RayCollision(TrackedEntity e) {
this(e.getEyeLocation());
}
public RayCollision(Location l) {
public RayCollision(KLocation l) {
this(l.toVector(),l.getDirection());
}
public RayCollision(Vector position, Vector direction) {
public RayCollision(Vector3d position, Vector3d direction) {
this.originX = position.getX();
this.originY = position.getY();
this.originZ = position.getZ();
@@ -75,17 +75,17 @@ public class RayCollision implements CollisionBox {
this.directionZ = direction.getZ();
}
public Vector getOrigin() {
return new Vector(originX, originY, originZ);
public Vector3d getOrigin() {
return new Vector3d(originX, originY, originZ);
}
public Vector getDirection() {
return new Vector(directionX, directionY, directionZ);
public Vector3d getDirection() {
return new Vector3d(directionX, directionY, directionZ);
}
@Override
public boolean isCollided(CollisionBox other) {
if (other instanceof RayCollision) {
if (other instanceof RayCollision) {
return false; // lol no support
} else {
List<SimpleCollisionBox> boxes = new ArrayList<>();
@@ -141,7 +141,7 @@ public class RayCollision implements CollisionBox {
public List<CollisionBox> boxesOnRay(APlayer player, 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.
KLocation[] locs = new KLocation[Math.max(2, amount)]; //We do a max to prevent NegativeArraySizeException.
List<CollisionBox> boxes = new ArrayList<>();
ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
@@ -152,7 +152,7 @@ public class RayCollision implements CollisionBox {
int fy = MathHelper.floor_double(originY + (directionY * ix));
int fz = MathHelper.floor_double(originZ + (directionZ * ix));
WrappedBlock block = player.getBlockUpdateHandler().getBlock(fx, fy, fz);
WrappedBlock block = player.getWorldTracker().getBlock(fx, fy, fz);
if (block == null) continue;
@@ -173,7 +173,7 @@ public class RayCollision implements CollisionBox {
public WrappedBlock getClosestBlockOfType(APlayer player, int bitmask, double distance) {
int amount = Math.round((float) (distance / 0.5));
Location[] locs = new Location[Math.max(2, amount)]; //We do a max
KLocation[] locs = new KLocation[Math.max(2, amount)]; //We do a max
ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
for (int i = 0; i < locs.length; i++) {
@@ -183,7 +183,7 @@ public class RayCollision implements CollisionBox {
int fy = MathHelper.floor_double(originY + (directionY * ix));
int fz = MathHelper.floor_double(originZ + (directionZ * ix));
WrappedBlock block = player.getBlockUpdateHandler().getBlock(fx, fy, fz);
WrappedBlock block = player.getWorldTracker().getBlock(fx, fy, fz);
if(block == null || !Materials.checkFlag(block.getType(), bitmask)) continue;
@@ -228,7 +228,7 @@ public class RayCollision implements CollisionBox {
RayTrace trace = new RayTrace(ray.getOrigin(), ray.getDirection());
Vector point = trace.positionOfIntersection(box, Math.max(0, dist - range), 0.01);
Vector3d point = trace.positionOfIntersection(box, Math.max(0, dist - range), 0.01);
return ray.getOrigin().distance(point);
}
@@ -347,23 +347,23 @@ public class RayCollision implements CollisionBox {
}
}
public Vector collisionPoint(SimpleCollisionBox box) {
public Vector3d collisionPoint(SimpleCollisionBox box) {
Tuple<Double, Double> p = new Tuple<>();
if (box==null||!intersect(this,box,p))
return null;
Vector vector = new Vector(directionX,directionY,directionZ);
Vector3d vector = new Vector3d(directionX,directionY,directionZ);
vector.normalize();
vector.multiply(p.one);
vector.add(new Vector(originX,originY,originZ));
vector.add(new Vector3d(originX,originY,originZ));
return vector;
}
public Vector collisionPoint(double dist) {
Vector vector = new Vector(directionX,directionY,directionZ);
public Vector3d collisionPoint(double dist) {
Vector3d vector = new Vector3d(directionX,directionY,directionZ);
vector.normalize();
vector.multiply(dist);
vector.add(new Vector(originX,originY,originZ));
vector.add(new Vector3d(originX,originY,originZ));
return vector;
}
}
@@ -1,6 +1,7 @@
package dev.brighten.ac.utils.world.types;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.Helper;
import dev.brighten.ac.utils.KLocation;
@@ -54,7 +55,7 @@ public class SimpleCollisionBox implements CollisionBox {
maxZ = width / 2;
}
public SimpleCollisionBox(Vector min, Vector max) {
public SimpleCollisionBox(Vector3d min, Vector3d max) {
this(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ());
}
@@ -76,6 +77,13 @@ public class SimpleCollisionBox implements CollisionBox {
maxY += height;
}
public SimpleCollisionBox(Vector3d vec, double width, double height) {
this(vec.getX(), vec.getY(), vec.getZ(), vec.getX(), vec.getY(), vec.getZ());
expand(width / 2, 0, width / 2);
maxY += height;
}
public void sort() {
double temp;
if (minX >= maxX) {
@@ -196,26 +204,26 @@ public class SimpleCollisionBox implements CollisionBox {
return this;
}
public Vector[] corners() {
public Vector3d[] corners() {
sort();
Vector[] vectors = new Vector[8];
vectors[0] = new Vector(minX, minY, minZ);
vectors[1] = new Vector(minX, minY, maxZ);
vectors[2] = new Vector(maxX, minY, minZ);
vectors[3] = new Vector(maxX, minY, maxZ);
vectors[4] = new Vector(minX, maxY, minZ);
vectors[5] = new Vector(minX, maxY, maxZ);
vectors[6] = new Vector(maxX, maxY, minZ);
vectors[7] = new Vector(maxX, maxY, maxZ);
Vector3d[] vectors = new Vector3d[8];
vectors[0] = new Vector3d(minX, minY, minZ);
vectors[1] = new Vector3d(minX, minY, maxZ);
vectors[2] = new Vector3d(maxX, minY, minZ);
vectors[3] = new Vector3d(maxX, minY, maxZ);
vectors[4] = new Vector3d(minX, maxY, minZ);
vectors[5] = new Vector3d(minX, maxY, maxZ);
vectors[6] = new Vector3d(maxX, maxY, minZ);
vectors[7] = new Vector3d(maxX, maxY, maxZ);
return vectors;
}
public Vector min() {
return new Vector(minX, minY, minZ);
public Vector3d min() {
return new Vector3d(minX, minY, minZ);
}
public Vector max() {
return new Vector(maxX, maxY, maxZ);
public Vector3d max() {
return new Vector3d(maxX, maxY, maxZ);
}
@Override
@@ -1,11 +1,11 @@
package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.util.MathUtil;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import lombok.Data;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.Vector;
import org.joml.Vector2d;
import java.util.Objects;
@@ -41,14 +41,18 @@ public class KLocation implements Cloneable {
this.timeStamp = System.currentTimeMillis();
}
public KLocation(Vector vector) {
public KLocation(Location location) {
this(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
public KLocation(Vector3d vector) {
this.x = vector.getX();
this.y = vector.getY();
this.z = vector.getZ();
this.timeStamp = System.currentTimeMillis();
}
public KLocation(Location location) {
public KLocation(KLocation location) {
this.x = location.getX();
this.y = location.getY();
this.z = location.getZ();
@@ -57,12 +61,12 @@ public class KLocation implements Cloneable {
this.timeStamp = System.currentTimeMillis();
}
public Vector toVector() {
return new Vector(x, y, z);
public Vector3d toVector() {
return new Vector3d(x, y, z);
}
public Vector3d toVector3d() {
return new Vector3d(x, y, z);
public Vector3i toVector3i() {
return new Vector3i((int) x, (int) y, (int) z);
}
public Location toLocation(World world) {
@@ -112,8 +116,27 @@ public class KLocation implements Cloneable {
return this;
}
public Vector getDirection() {
return MathUtils.getDirection(this);
public Vector3d getDirection() {
double rotX = this.getYaw();
double rotY = this.getPitch();
double x, y, z;
y = -Math.sin(Math.toRadians(rotY));
double xz = Math.cos(Math.toRadians(rotY));
x = -xz * Math.sin(Math.toRadians(rotX));
z = xz * Math.cos(Math.toRadians(rotX));
return new Vector3d(x, y, z);
}
public int getBlockX() {
return MathUtil.floor(x);
}
public int getBlockY() {
return MathUtil.floor(y);
}
public int getBlockZ() {
return MathUtil.floor(z);
}
@Override
@@ -1,5 +1,6 @@
package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.util.Vector3d;
import lombok.val;
import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.Location;
@@ -196,10 +197,6 @@ public class MathUtils {
return MathUtils.yawTo180D(playerRotation.getX() - expectedRotation.getX());
}
public static double getAngle(KLocation loc1, KLocation loc2) {
return getAngle(loc1.toLocation(null), loc2.toLocation(null));
}
public static float distanceBetweenAngles(float a, float b) {
final float first = a % 360;
final float second = b % 360;
@@ -544,16 +541,14 @@ public class MathUtils {
return (short) num;
}
/* Stolen from Bukkit */
public static Vector getDirection(KLocation loc) {
Vector vector = new Vector();
public static Vector3d getDirection(KLocation loc) {
Vector3d vector = new Vector3d();
double rotX = loc.getYaw();
double rotY = loc.getPitch();
vector.setY(-Math.sin(Math.toRadians(rotY)));
double xz = Math.cos(Math.toRadians(rotY));
vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
return vector;
return new Vector3d(-xz * Math.sin(Math.toRadians(rotX)),
-Math.sin(Math.toRadians(rotY)),
xz * Math.cos(Math.toRadians(rotX)));
}
@@ -704,12 +699,12 @@ public class MathUtils {
return squareRoot;
}
public static Vector getDirection(float yaw, float pitch) {
public static Vector3d getDirection(float yaw, float pitch) {
float f = MathHelper.cos(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI);
float f1 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI);
float f2 = -MathHelper.cos(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F);
float f3 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F);
return new Vector(f1 * f2, f3, f * f2);
return new Vector3d(f1 * f2, f3, f * f2);
}
public static float sqrt(float number) {
+1 -1
Submodule Neo updated: b45b76d09d...d1dd462bf3
+4
View File
@@ -30,6 +30,10 @@
</build>
<repositories>
<repository>
<id>maven-central</id>
<url>https://nexus.funkemunky.cc/repository/maven-central/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>