Merge main: apply array-based chunk storage to World.java, resolve BlockUpdateHandler conflict

Co-authored-by: funkemunky <30784509+funkemunky@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-20 16:07:21 +00:00
parent 1b860c9bd5
commit 440fec9eaf
55 changed files with 1245 additions and 833 deletions
+5 -5
View File
@@ -19,6 +19,10 @@
</properties> </properties>
<repositories> <repositories>
<repository>
<id>maven-central</id>
<url>https://nexus.funkemunky.cc/repository/maven-central/</url>
</repository>
<repository> <repository>
<id>viaversion-repo</id> <id>viaversion-repo</id>
<url>https://repo.viaversion.com</url> <url>https://repo.viaversion.com</url>
@@ -27,10 +31,6 @@
<id>spigot-repo</id> <id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository> </repository>
<repository>
<id>evokegames</id>
<url>https://maven.evokegames.gg/snapshots</url>
</repository>
<repository> <repository>
<id>aikar</id> <id>aikar</id>
<url>https://repo.aikar.co/content/groups/aikar/</url> <url>https://repo.aikar.co/content/groups/aikar/</url>
@@ -267,7 +267,7 @@
<dependency> <dependency>
<groupId>com.github.retrooper</groupId> <groupId>com.github.retrooper</groupId>
<artifactId>packetevents-spigot</artifactId> <artifactId>packetevents-spigot</artifactId>
<version>2.9.4</version> <version>2.11.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -17,6 +17,8 @@ import dev.brighten.ac.handler.PacketHandler;
import dev.brighten.ac.handler.entity.FakeEntityTracker; import dev.brighten.ac.handler.entity.FakeEntityTracker;
import dev.brighten.ac.handler.keepalive.KeepaliveProcessor; import dev.brighten.ac.handler.keepalive.KeepaliveProcessor;
import dev.brighten.ac.handler.keepalive.actions.ActionManager; 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.logging.LoggerManager;
import dev.brighten.ac.utils.*; import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.annotation.ConfigSetting; 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 dev.brighten.ac.utils.world.WorldInfo;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.PackagePrivate; import lombok.experimental.PackagePrivate;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
@@ -116,6 +119,9 @@ public class Anticheat extends JavaPlugin {
private final RollingAverageDouble tps = new RollingAverageDouble(4, 20); private final RollingAverageDouble tps = new RollingAverageDouble(4, 20);
private final Map<UUID, WorldInfo> worldInfoMap = new HashMap<>(); private final Map<UUID, WorldInfo> worldInfoMap = new HashMap<>();
@Setter
private Protocol protocol = new NoAPI();
private final List<BaseCommand> commands = new ArrayList<>(); private final List<BaseCommand> commands = new ArrayList<>();
public static boolean allowDebug = true; public static boolean allowDebug = true;
@@ -252,7 +258,7 @@ public class Anticheat extends JavaPlugin {
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
Anticheat.INSTANCE.getLogger().log(Level.SEVERE, "Check ID unregister failed", e); Anticheat.INSTANCE.getLogger().log(Level.SEVERE, "Check ID unregister failed", e);
} }
commandManager.getScheduler().cancelLocaleTask();
commandPropertiesManager = null; commandPropertiesManager = null;
try { try {
@@ -23,5 +23,5 @@ public @interface CheckData {
int punishVl() default 10; int punishVl() default 10;
ClientVersion minVersion() default ClientVersion.V_1_8; ClientVersion minVersion() default ClientVersion.V_1_8;
ClientVersion maxVersion() default ClientVersion.V_1_21_7; ClientVersion maxVersion() default ClientVersion.V_1_21_11;
} }
@@ -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.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; 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.WrapperPlayClientInteractEntity;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.Anticheat; 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.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.EntityData;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.util.Vector;
import java.util.*; import java.util.*;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@@ -46,7 +46,7 @@ public class Hitbox extends Check {
if(packet.getAction() != WrapperPlayClientInteractEntity.InteractAction.ATTACK) if(packet.getAction() != WrapperPlayClientInteractEntity.InteractAction.ATTACK)
return; 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; if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
attacks.add(new Tuple<>(entity.get(), attacks.add(new Tuple<>(entity.get(),
@@ -118,7 +118,7 @@ public class Hitbox extends Check {
boolean didSneakOrElytra = player.getInfo().getLastSneak().isNotPassed(40) boolean didSneakOrElytra = player.getInfo().getLastSneak().isNotPassed(40)
|| player.getInfo().getLastElytra().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().getYaw(),
player.getMovement().getTo().getLoc().getPitch()), player.getMovement().getTo().getLoc().getPitch()),
MathUtils.getDirection(player.getMovement().getFrom().getLoc().getYaw(), MathUtils.getDirection(player.getMovement().getFrom().getLoc().getYaw(),
@@ -126,7 +126,7 @@ public class Hitbox extends Check {
if(!didSneakOrElytra) { if(!didSneakOrElytra) {
to.add(0, 1.62f, 0); to.add(0, 1.62f, 0);
for (Vector direction : directions) { for (Vector3d direction : directions) {
for (SimpleCollisionBox targetBox : boxes) { for (SimpleCollisionBox targetBox : boxes) {
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox); 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 //Checking all possible eyeheights since client actions notoriously desync from the server side
} else { } else {
for (Vector direction : directions) { for (Vector3d direction : directions) {
for (double eyeHeight : player.getMovement().getEyeHeights()) { for (double eyeHeight : player.getMovement().getEyeHeights()) {
for (SimpleCollisionBox targetBox : boxes) { for (SimpleCollisionBox targetBox : boxes) {
final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox); 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, debug("buffer: %.3f distance=%.2f hits=%s sneaking=%s", buffer, distance, hits,
player.getInfo().isSneaking()); player.getInfo().isSneaking());
} else if(player.getEntityLocationHandler().streak > 1) { } else if(player.getEntityTrackHandler().streak > 1) {
if (++hbuffer > 5) { if (++hbuffer > 5) {
flag("%.1f;%.1f;%.1f", entity.getNewEntityLocation().x, entity.getNewEntityLocation().y, entity.getNewEntityLocation().z); 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; 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.WrapperPlayClientAnimation;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.api.check.CheckType;
@@ -29,10 +28,10 @@ public class KABot extends Check {
@Bind @Bind
WAction<WrapperPlayClientInteractEntity> packet = packet -> { WAction<WrapperPlayClientInteractEntity> packet = packet -> {
val optional = player.getEntityLocationHandler().getTrackedEntity(packet.getEntityId()); val optional = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(packet.getEntityId());
if(optional.isPresent() if(optional.isPresent()
&& (player.getEntityLocationHandler().clientHasEntity.get() && (player.getEntityTrackHandler().clientHasEntity.get()
|| !optional.get().getFakeMobs().isEmpty())) { || !optional.get().getFakeMobs().isEmpty())) {
if(++buffer > 3) { if(++buffer > 3) {
flag("Attacked player without attacking bot!"); flag("Attacked player without attacking bot!");
@@ -1,6 +1,6 @@
package dev.brighten.ac.check.impl.combat.killaura; 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 com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check; 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.EntityData;
import dev.brighten.ac.utils.world.types.RayCollision; import dev.brighten.ac.utils.world.types.RayCollision;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.util.Vector;
/** /**
* @author funkemunky * @author funkemunky
@@ -43,14 +42,13 @@ public class KATrace extends Check {
return; return;
} }
var trackedEntity = player.getEntityLocationHandler().getTrackedEntity(player.getInfo().getTarget().getEntityId()); var trackedEntity = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(player.getInfo().getTarget().getEntityId());
if(trackedEntity.isEmpty()) { if(trackedEntity.isEmpty()) {
return; return;
} }
// Getting the target's bounding box // Getting the target's bounding box
SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget() SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget().getLocation(), trackedEntity.get());
.getLocation(), trackedEntity.get());
if(targetBox == null) return; if(targetBox == null) return;
@@ -59,12 +57,12 @@ public class KATrace extends Check {
// Setting the player's eye height based on their sneak status // Setting the player's eye height based on their sneak status
origin.add(0, player.getEyeHeight(), 0); origin.add(0, player.getEyeHeight(), 0);
final Vector originVec = origin.toVector(); final Vector3d originVec = origin.toVector();
// Setting a trace based on their view direction // Setting a trace based on their view direction
RayCollision collision = new RayCollision(originVec, origin.getDirection()); 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 the ray isn't collided, we might as well not run this check. Just a simple boxes on array check
if(targetPoint == null) return; if(targetPoint == null) return;
@@ -84,7 +82,7 @@ public class KATrace extends Check {
continue; continue;
// We want to shrink the box slightly since there is a bit of a margin of error in the ray trace. // 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) { if (point != null && originVec.distanceSquared(point) < dist - 0.2) {
rayCollidedOnBlock = true; rayCollidedOnBlock = true;
@@ -31,7 +31,7 @@ public class KACalc extends KListener {
@Bind @Bind
WAction<WrapperPlayClientPlayerFlying> flying = packet -> { WAction<WrapperPlayClientPlayerFlying> flying = packet -> {
if(player.getInfo().getTarget() == null || player.getInfo().lastAttack.isPassed(40)) return; 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()); .getTrackedEntity(player.getInfo().getTarget().getEntityId());
if(optional.isEmpty()) return; if(optional.isEmpty()) return;
@@ -46,7 +46,7 @@ public class KACalc extends KListener {
KLocation originKLoc = player.getMovement().getTo().getLoc().clone() KLocation originKLoc = player.getMovement().getTo().getLoc().clone()
.add(0, player.getInfo().isSneaking() ? 1.54f : 1.62f, 0); .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()); KLocation targetLocation = new KLocation(current.getX(), current.getY(), current.getZ());
var rotations = MathUtils var rotations = MathUtils
.getRotation(originKLoc, targetLocation.clone().add(0, halfHeight, 0)); .getRotation(originKLoc, targetLocation.clone().add(0, halfHeight, 0));
@@ -1,6 +1,7 @@
package dev.brighten.ac.check.impl.movement; package dev.brighten.ac.check.impl.movement;
import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag; 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.client.WrapperPlayClientPlayerFlying;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerPositionAndLook; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerPositionAndLook;
import dev.brighten.ac.Anticheat; 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.objects.evicting.EvictingSet;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.util.Vector;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -31,7 +31,7 @@ public class Phase extends Check {
} }
private int ticks; private int ticks;
private final Set<Vector> POSITIONS = new EvictingSet<>(10); private final Set<Vector3d> POSITIONS = new EvictingSet<>(10);
private Location teleportLoc = null; private Location teleportLoc = null;
@Bind @Bind
@@ -1,6 +1,7 @@
package dev.brighten.ac.check.impl.movement.speed; package dev.brighten.ac.check.impl.movement.speed;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; 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 com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check; import dev.brighten.ac.check.Check;
@@ -36,11 +37,11 @@ public class Speed extends Check {
moveFactor+= (float) (moveFactor * 0.30000001192092896D); 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) moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SPEED)
* (0.200000000298023224D)) * moveFactor); * (0.200000000298023224D)) * moveFactor);
if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW)) if(player.getPotionHandler().hasPotionEffect(PotionTypes.SLOWNESS))
moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SLOW) moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SLOW)
* (-0.15000000596046448D)) * moveFactor); * (-0.15000000596046448D)) * moveFactor);
@@ -1,6 +1,8 @@
package dev.brighten.ac.check.impl.movement.velocity; package dev.brighten.ac.check.impl.movement.velocity;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; 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 com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.api.check.CheckType;
import dev.brighten.ac.check.Check; 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.KLocation;
import dev.brighten.ac.utils.MathUtils; import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.annotation.Bind; 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.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.timer.impl.TickTimer;
import lombok.val; import lombok.val;
import me.hydro.emulator.util.mcp.MathHelper; import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -61,8 +61,8 @@ public class VelocityB extends Check {
val underBlockLoc = previousFrom != null val underBlockLoc = previousFrom != null
? player.getMovement().getFrom().getLoc() : player.getMovement().getTo().getLoc(); ? player.getMovement().getFrom().getLoc() : player.getMovement().getTo().getLoc();
WrappedBlock underMaterial = player.getBlockUpdateHandler() WrappedBlock underMaterial = player.getWorldTracker()
.getBlock(new IntVector(MathHelper.floor_double(underBlockLoc.getX()), .getBlock(new Vector3i(MathHelper.floor_double(underBlockLoc.getX()),
MathHelper.floor_double(underBlockLoc.getY() - 1), MathHelper.floor_double(underBlockLoc.getY() - 1),
MathHelper.floor_double(underBlockLoc.getZ()))); MathHelper.floor_double(underBlockLoc.getZ())));
@@ -87,8 +87,8 @@ public class VelocityB extends Check {
double pmotionx = 0, pmotionz = 0; double pmotionx = 0, pmotionz = 0;
boolean onGround = player.getMovement().getFrom().isOnGround(); boolean onGround = player.getMovement().getFrom().isOnGround();
val speed = player.getPotionHandler().getEffectByType(PotionEffectType.SPEED); val speed = player.getPotionHandler().getEffectByType(PotionTypes.SPEED);
val slow = player.getPotionHandler().getEffectByType(PotionEffectType.SLOW); val slow = player.getPotionHandler().getEffectByType(PotionTypes.SLOWNESS);
for (Iteration iteration : iterations) { for (Iteration iteration : iterations) {
float forward = iteration.f, strafe = iteration.s; float forward = iteration.f, strafe = iteration.s;
@@ -138,9 +138,9 @@ public class VelocityB extends Check {
aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D; aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D;
if (speed.isPresent()) if (speed.isPresent())
aiMoveSpeed += (speed.get().getAmplifier() + 1) * 0.20000000298023224D * aiMoveSpeed; aiMoveSpeed += (speed.get().properties().amplifier() + 1) * 0.20000000298023224D * aiMoveSpeed;
if (slow.isPresent()) if (slow.isPresent())
aiMoveSpeed += (slow.get().getAmplifier() + 1) * -0.15000000596046448D * aiMoveSpeed; aiMoveSpeed += (slow.get().properties().amplifier() + 1) * -0.15000000596046448D * aiMoveSpeed;
float f5; float f5;
if (onGround) { if (onGround) {
@@ -1,6 +1,7 @@
package dev.brighten.ac.check.impl.world; package dev.brighten.ac.check.impl.world;
import com.github.retrooper.packetevents.util.Vector3d; 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.WrapperPlayClientPlayerBlockPlacement;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.api.check.CheckType;
@@ -35,7 +36,7 @@ public class BlockA extends Check {
WAction<WrapperPlayClientPlayerBlockPlacement> blockPlace = packet -> { WAction<WrapperPlayClientPlayerBlockPlacement> blockPlace = packet -> {
Vector3d loc = packet.getBlockPosition().toVector3d(); 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()); 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.handler.block.WrappedBlock;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.annotation.Bind; 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.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.BlockData; 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) @CheckData(name = "Block (D)", checkId = "blockc", type = CheckType.INTERACT)
public class BlockD extends Check { public class BlockD extends Check {
@@ -45,7 +45,7 @@ public class BlockD extends Check {
packet.getFace().getModY(), packet.getFace().getModY(),
packet.getFace().getModZ()); packet.getFace().getModZ());
WrappedBlock block = new WrappedBlock(new IntVector(packet.getBlockPosition()), WrappedBlock block = new WrappedBlock(packet.getBlockPosition(),
placedType, placedType,
WrappedBlockState.getDefaultState(placedType)); WrappedBlockState.getDefaultState(placedType));
blockPlaceLocations.put(blockpos, block); blockPlaceLocations.put(blockpos, block);
@@ -7,11 +7,12 @@ import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.player.User; import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.world.dimension.DimensionType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; 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.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import dev.brighten.ac.Anticheat; import dev.brighten.ac.Anticheat;
import dev.brighten.ac.api.spigot.impl.LegacyPlayer; import dev.brighten.ac.api.spigot.impl.LegacyPlayer;
import dev.brighten.ac.api.spigot.impl.ModernPlayer; import dev.brighten.ac.api.spigot.impl.ModernPlayer;
@@ -22,17 +23,20 @@ import dev.brighten.ac.data.info.GeneralInformation;
import dev.brighten.ac.data.info.LagInformation; import dev.brighten.ac.data.info.LagInformation;
import dev.brighten.ac.data.obj.InstantAction; import dev.brighten.ac.data.obj.InstantAction;
import dev.brighten.ac.data.obj.NormalAction; 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.MovementHandler;
import dev.brighten.ac.handler.PotionHandler; import dev.brighten.ac.handler.PotionHandler;
import dev.brighten.ac.handler.VelocityHandler; import dev.brighten.ac.handler.VelocityHandler;
import dev.brighten.ac.handler.block.BlockUpdateHandler; import dev.brighten.ac.handler.block.BlockUpdateHandler;
import dev.brighten.ac.handler.block.World;
import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.handler.entity.FakeMob;
import dev.brighten.ac.handler.keepalive.KeepAlive; import dev.brighten.ac.handler.keepalive.KeepAlive;
import dev.brighten.ac.handler.protocol.Protocol;
import dev.brighten.ac.messages.Messages; import dev.brighten.ac.messages.Messages;
import dev.brighten.ac.packet.TransactionServerWrapper; 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.objects.evicting.EvictingList;
import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer; import dev.brighten.ac.utils.timer.impl.MillisTimer;
@@ -49,7 +53,6 @@ import me.hydro.emulator.object.input.DataSupplier;
import me.hydro.emulator.util.mcp.AxisAlignedBB; import me.hydro.emulator.util.mcp.AxisAlignedBB;
import me.hydro.emulator.util.mcp.BlockPos; import me.hydro.emulator.util.mcp.BlockPos;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@@ -72,10 +75,10 @@ public class APlayer {
private VelocityHandler velocityHandler; private VelocityHandler velocityHandler;
@Getter @Getter
private EntityLocationHandler entityLocationHandler; private EntityTrackHandler entityTrackHandler;
@Getter @Getter
private BlockUpdateHandler blockUpdateHandler; private BlockUpdateHandler worldTracker;
@Getter @Getter
private CheckHandler checkHandler; private CheckHandler checkHandler;
@@ -138,87 +141,103 @@ public class APlayer {
this.movement = new MovementHandler(this); this.movement = new MovementHandler(this);
this.potionHandler = new PotionHandler(this); this.potionHandler = new PotionHandler(this);
this.velocityHandler = new VelocityHandler(this); this.velocityHandler = new VelocityHandler(this);
this.entityLocationHandler = new EntityLocationHandler(this); this.entityTrackHandler = new EntityTrackHandler(this);
this.blockUpdateHandler = new BlockUpdateHandler(this); this.worldTracker = new BlockUpdateHandler(this);
this.checkHandler = new CheckHandler(this); this.checkHandler = new CheckHandler(this);
this.info = new GeneralInformation(); this.info = new GeneralInformation();
this.lagInfo = new LagInformation(); this.lagInfo = new LagInformation();
this.blockInfo = new BlockInformation(this); this.blockInfo = new BlockInformation(this);
worldTracker.getCurrentWorld().set(new World(bukkitPlayer.getWorld().getName()));
creation.reset(); creation.reset();
playerVersion = ClientVersion.getById(Anticheat.INSTANCE.getProtocol().getPlayerVersion(this));
Anticheat.INSTANCE.getScheduler().schedule(() -> { Anticheat.INSTANCE.getScheduler().schedule(() -> {
// Grabbing the protocol version of the player. // Grabbing the protocol version of the player.
Anticheat.INSTANCE.getLogger().info("Attempting Getting player version for " + getBukkitPlayer().getName()); 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; this.playerVersion = version;
Anticheat.INSTANCE.getLogger().info("Got player version " + version.name() + " for " + getBukkitPlayer().getName()); Anticheat.INSTANCE.getLogger().info("Got player version " + version.name() + " for " + getBukkitPlayer().getName());
if(PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9)) {
this.wrappedPlayer = new LegacyPlayer(getBukkitPlayer());
} else this.wrappedPlayer = new ModernPlayer(getBukkitPlayer());
EMULATOR = new Emulator(new DataSupplier() {
@Override
public List<AxisAlignedBB> getCollidingBoxes(AxisAlignedBB bb) {
SimpleCollisionBox sbc = new SimpleCollisionBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
// Greater than 20? We want to truncate to prevent huge processing cost
if(sbc.min().distanceSquared(sbc.max()) > 400) {
sbc.maxX = sbc.minX + Math.min(sbc.maxX - sbc.minX, 20);
sbc.maxY = sbc.minY + Math.max(sbc.maxY - sbc.minY, 20);
sbc.maxZ = sbc.minZ + Math.max(sbc.maxZ - sbc.minZ, 20);
}
List<AxisAlignedBB> axisAlignedBBs = new ArrayList<>();
for (SimpleCollisionBox bb2 : Helper.getCollisions(APlayer.this,
sbc)) {
axisAlignedBBs
.add(new AxisAlignedBB(bb2.minX, bb2.minY, bb2.minZ, bb2.maxX, bb2.maxY, bb2.maxZ));
}
return axisAlignedBBs;
}
@Override
public Block getBlockAt(BlockPos blockPos) {
//Optional<org.bukkit.block.Block>
var block = APlayer.this.getBlockUpdateHandler()
.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ());
StateType type = block.getType();
if(type == StateTypes.SLIME_BLOCK) {
return new BlockSlime();
} else if(type == StateTypes.SOUL_SAND) {
return new BlockSoulSand();
} else if(type == StateTypes.COBWEB) {
return new BlockWeb();
} else if(type == StateTypes.ICE || type == StateTypes.PACKED_ICE || type == StateTypes.FROSTED_ICE) {
return new BlockIce();
} else if(type == StateTypes.BLUE_ICE) {
return new BlockBlueIce();
}
return new Block();
}
}, getPlayerVersion().getProtocolVersion());
generateEntities();
// Enabling alerts for players on join if they have the permissions to
if(getBukkitPlayer().hasPermission("anticheat.command.alerts")
|| getBukkitPlayer().hasPermission("anticheat.alerts")) {
Check.alertsEnabled.add(getUuid());
getBukkitPlayer().spigot().sendMessage(Messages.ALERTS_ON);
}
initialized = true;
Anticheat.INSTANCE.getRunUtils().task(() -> checkHandler.initChecks());
}, 100, TimeUnit.MILLISECONDS); }, 100, TimeUnit.MILLISECONDS);
if(PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9)) {
this.wrappedPlayer = new LegacyPlayer(getBukkitPlayer());
} else this.wrappedPlayer = new ModernPlayer(getBukkitPlayer());
Cache<AxisAlignedBB, List<AxisAlignedBB>> collisionCache = CacheBuilder.newBuilder()
.maximumSize(200)
.expireAfterWrite(100, TimeUnit.MILLISECONDS)
.build();
EMULATOR = new Emulator(new DataSupplier() {
@Override
public List<AxisAlignedBB> getCollidingBoxes(AxisAlignedBB bb) {
var cacheIfPresent = collisionCache.getIfPresent(bb);
if(cacheIfPresent != null) return cacheIfPresent;
SimpleCollisionBox sbc = new SimpleCollisionBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
// Greater than 20? We want to truncate to prevent huge processing cost
if(sbc.min().distanceSquared(sbc.max()) > 400) {
sbc.maxX = sbc.minX + Math.min(sbc.maxX - sbc.minX, 20);
sbc.maxY = sbc.minY + Math.max(sbc.maxY - sbc.minY, 20);
sbc.maxZ = sbc.minZ + Math.max(sbc.maxZ - sbc.minZ, 20);
}
List<AxisAlignedBB> axisAlignedBBs = new ArrayList<>();
for (SimpleCollisionBox bb2 : Helper.getCollisions(APlayer.this,
sbc)) {
axisAlignedBBs
.add(new AxisAlignedBB(bb2.minX, bb2.minY, bb2.minZ, bb2.maxX, bb2.maxY, bb2.maxZ));
}
collisionCache.put(bb, axisAlignedBBs);
return axisAlignedBBs;
}
@Override
public Block getBlockAt(BlockPos blockPos) {
//Optional<org.bukkit.block.Block>
var block = APlayer.this.getWorldTracker()
.getBlock(blockPos.getX(), blockPos.getY(), blockPos.getZ());
StateType type = block.getType();
if(type == StateTypes.SLIME_BLOCK) {
return new BlockSlime();
} else if(type == StateTypes.SOUL_SAND) {
return new BlockSoulSand();
} else if(type == StateTypes.COBWEB) {
return new BlockWeb();
} else if(type == StateTypes.ICE || type == StateTypes.PACKED_ICE || type == StateTypes.FROSTED_ICE) {
return new BlockIce();
} else if(type == StateTypes.BLUE_ICE) {
return new BlockBlueIce();
}
return new Block();
}
}, getPlayerVersion().getProtocolVersion());
generateEntities();
// Enabling alerts for players on join if they have the permissions to
if(getBukkitPlayer().hasPermission("anticheat.command.alerts")
|| getBukkitPlayer().hasPermission("anticheat.alerts")) {
Check.alertsEnabled.add(getUuid());
getBukkitPlayer().spigot().sendMessage(Messages.ALERTS_ON);
}
initialized = true;
Anticheat.INSTANCE.getRunUtils().task(() -> checkHandler.initChecks());
} }
private void generateEntities() { private void generateEntities() {
@@ -228,7 +247,7 @@ public class APlayer {
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1)); 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<>(); List<EntityData<?>> dataList = new ArrayList<>();
@@ -330,10 +349,6 @@ public class APlayer {
user.writePacketSilently(packet); user.writePacketSilently(packet);
} }
public DimensionType getDimensionType() {
return user.getDimensionType();
}
public void sendPacket(PacketWrapper<?> packet) { public void sendPacket(PacketWrapper<?> packet) {
user.sendPacket(packet); user.sendPacket(packet);
} }
@@ -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.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; 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.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.Anticheat; import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.handler.entity.TrackedEntity;
@@ -132,11 +133,11 @@ public class BlockInformation {
} }
final StateType type = 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) { if (type != StateTypes.AIR) {
IntVector vec = new IntVector(x, y, z); Vector3i vec = new Vector3i(x, y, z);
CollisionBox blockBox = BlockData.getData(type) CollisionBox blockBox = BlockData.getData(type)
.getBox(player, vec, player.getPlayerVersion()); .getBox(player, vec, player.getPlayerVersion());
@@ -1,10 +1,12 @@
package dev.brighten.ac.data.info; package dev.brighten.ac.data.info;
import com.github.retrooper.packetevents.util.Vector3d; 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.block.WrappedBlock;
import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.packet.PlayerCapabilities; import dev.brighten.ac.packet.PlayerCapabilities;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.KPotionEffect;
import dev.brighten.ac.utils.PastLocation; import dev.brighten.ac.utils.PastLocation;
import dev.brighten.ac.utils.math.RollingAverage; import dev.brighten.ac.utils.math.RollingAverage;
import dev.brighten.ac.utils.objects.evicting.EvictingList; 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 dev.brighten.ac.utils.timer.impl.TickTimer;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bukkit.entity.LivingEntity;
import org.bukkit.potion.PotionEffect;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -33,8 +33,8 @@ public class GeneralInformation {
lastBlockUpdate = new TickTimer(), lastMiscNear = new TickTimer(), lastHalfBlock = new TickTimer(), lastBlockUpdate = new TickTimer(), lastMiscNear = new TickTimer(), lastHalfBlock = new TickTimer(),
lastFence = new TickTimer(), lastFakeBotHit = new TickTimer(), lastInventoryOpen = new TickTimer(), lastFence = new TickTimer(), lastFakeBotHit = new TickTimer(), lastInventoryOpen = new TickTimer(),
botAttack = new TickTimer(), lastAttack = new TickTimer(), lastCanceledFlying = new TickTimer(); botAttack = new TickTimer(), lastAttack = new TickTimer(), lastCanceledFlying = new TickTimer();
public LivingEntity target; public TrackedEntity target;
public Optional<PotionEffect> groundJumpBoost; public Optional<KPotionEffect> groundJumpBoost = Optional.empty();
public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative, public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative,
sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock, sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock,
inventoryOpen, swimming; inventoryOpen, swimming;
@@ -46,4 +46,7 @@ public class GeneralInformation {
public List<Vector3d> velocityHistory = Collections.synchronizedList(new EvictingList<>(5)); public List<Vector3d> velocityHistory = Collections.synchronizedList(new EvictingList<>(5));
public List<PlayerCapabilities> possibleCapabilities = new ArrayList<>(); public List<PlayerCapabilities> possibleCapabilities = new ArrayList<>();
private int clientGroundTicks, clientAirTicks; private int clientGroundTicks, clientAirTicks;
private double walkSpeed, flySpeed;
private PlayerInput playerInput = PlayerInput.NONE;
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; package dev.brighten.ac.data.obj;
import dev.brighten.ac.handler.block.World;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bukkit.World;
@Getter @Getter
@Setter @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; package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; 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.Anticheat;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.ItemBuilder; import dev.brighten.ac.utils.ItemBuilder;
import dev.brighten.ac.utils.Materials; import dev.brighten.ac.utils.Materials;
import dev.brighten.ac.utils.annotation.Init; 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.BlockData;
import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.EntityData;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
@@ -31,7 +31,7 @@ import java.util.stream.Collectors;
@Init @Init
public class BBRevealHandler implements Listener { 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<>(); private final Set<Entity> entitiesToShow = new HashSet<>();
public static BBRevealHandler INSTANCE; public static BBRevealHandler INSTANCE;
@@ -52,9 +52,9 @@ public class BBRevealHandler implements Listener {
if(player == null || !player.getWrappedPlayer().getItemInHand().isSimilar(wand)) return; if(player == null || !player.getWrappedPlayer().getItemInHand().isSimilar(wand)) return;
if(event.getAction() == Action.RIGHT_CLICK_BLOCK) { 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()); event.getClickedBlock().getY(), event.getClickedBlock().getZ());
Set<IntVector> blocksToShow = this.blocksToShow Set<Vector3i> blocksToShow = this.blocksToShow
.computeIfAbsent(event.getPlayer().getUniqueId(), k -> new HashSet<>()); .computeIfAbsent(event.getPlayer().getUniqueId(), k -> new HashSet<>());
if(blocksToShow.contains(blockLoc)) { if(blocksToShow.contains(blockLoc)) {
blocksToShow.remove(blockLoc); blocksToShow.remove(blockLoc);
@@ -63,11 +63,11 @@ public class BBRevealHandler implements Listener {
.create()); .create());
} else { } else {
blocksToShow.add(blockLoc); 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: ") event.getPlayer().spigot().sendMessage(new ComponentBuilder("Now showing block: ")
.color(ChatColor.GREEN).color(ChatColor.WHITE).append(event.getClickedBlock().getType().name()) .color(ChatColor.GREEN).color(ChatColor.WHITE).append(event.getClickedBlock().getType().name())
.color(ChatColor.GRAY) .color(ChatColor.GRAY)
.append(" flags: " + block.getBlockState().getType() + " | " + Materials.checkFlag(block.getType(), Materials.COLLIDABLE) + "," + .append(" flags: " + block.getType() + " | " + block.getType().isSolid() + "," +
Materials.checkFlag(block.getType(), Materials.SOLID) + "," + Materials.checkFlag(block.getType(), Materials.LIQUID)) Materials.checkFlag(block.getType(), Materials.SOLID) + "," + Materials.checkFlag(block.getType(), Materials.LIQUID))
.color(ChatColor.RED) .color(ChatColor.RED)
.append(" | box=" + BlockData.getData(block.getType()).getBox(player, blockLoc, player.getPlayerVersion()).downCast().stream().map(SimpleCollisionBox::toString).collect(Collectors.joining(", "))) .append(" | box=" + BlockData.getData(block.getType()).getBox(player, blockLoc, player.getPlayerVersion()).downCast().stream().map(SimpleCollisionBox::toString).collect(Collectors.joining(", ")))
@@ -107,7 +107,7 @@ public class BBRevealHandler implements Listener {
if(player.isEmpty()) return; if(player.isEmpty()) return;
blocks.forEach(blockLoc -> { 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()) var blockBox = BlockData.getData(block.getType())
.getBox(player.get(), blockLoc, player.get().getPlayerVersion()); .getBox(player.get(), blockLoc, player.get().getPlayerVersion());
@@ -1,14 +1,17 @@
package dev.brighten.ac.handler; 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.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; 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.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; 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.WrapperPlayServerDestroyEntities;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityPositionSync; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityPositionSync;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport; 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.data.APlayer;
import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.handler.entity.FakeMob;
import dev.brighten.ac.handler.entity.TrackedEntity; 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.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer; import dev.brighten.ac.utils.timer.impl.MillisTimer;
import dev.brighten.ac.utils.world.types.RayCollision; import dev.brighten.ac.utils.world.types.RayCollision;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.bukkit.util.Vector;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@RequiredArgsConstructor @RequiredArgsConstructor
public class EntityLocationHandler { public class EntityTrackHandler {
private final APlayer data; private final APlayer data;
@Getter
private Map<Integer, TrackedEntity> trackedEntities = new Int2ObjectArrayMap<>();
private final Timer lastFlying = new MillisTimer(); private final Timer lastFlying = new MillisTimer();
public Set<Integer> canCreateMob = new HashSet<>(); public Set<Integer> canCreateMob = new HashSet<>();
@@ -43,7 +41,8 @@ public class EntityLocationHandler {
EntityTypes.WITCH, EntityTypes.COW, EntityTypes.CREEPER); EntityTypes.WITCH, EntityTypes.COW, EntityTypes.CREEPER);
public Optional<Integer> getTargetOfFakeMob(int fakeMobId) { 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)) { if(value.getFakeMobs().stream().anyMatch(mob -> mob.getEntityId() == fakeMobId)) {
return Optional.of(value.getEntityId()); return Optional.of(value.getEntityId());
} }
@@ -51,23 +50,6 @@ public class EntityLocationHandler {
return Optional.empty(); 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 * We are processing PacketPlayInFlying to iterate the tracked entity locations
@@ -81,7 +63,7 @@ public class EntityLocationHandler {
processZombie(); processZombie();
trackedEntities.values().forEach(entity -> { data.getWorldTracker().getCurrentWorld().get().getTrackedEntities().values().forEach(entity -> {
var oldLoc = entity.getOldEntityLocation(); var oldLoc = entity.getOldEntityLocation();
var newLoc = entity.getNewEntityLocation(); var newLoc = entity.getNewEntityLocation();
@@ -109,7 +91,8 @@ public class EntityLocationHandler {
* @param packet WrappedOutRelativePosition * @param packet WrappedOutRelativePosition
*/ */
void onRelPosition(WPacketPlayOutEntity packet) { 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; if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
@@ -132,7 +115,8 @@ public class EntityLocationHandler {
} }
void onPositionSync(WrapperPlayServerEntityPositionSync packet) { 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; if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return;
@@ -161,7 +145,8 @@ public class EntityLocationHandler {
* @param packet WrappedOutEntityTeleportPacket * @param packet WrappedOutEntityTeleportPacket
*/ */
void onTeleportSent(WrapperPlayServerEntityTeleport packet) { 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; 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, * 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) { public void removeFakeMob(int id) {
if(trackedEntities.containsKey(id)) { if(data.getWorldTracker().getCurrentWorld().get()
List<FakeMob> mobs = getTrackedEntity(id).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>()); .getTrackedEntities().containsKey(id)) {
List<FakeMob> mobs = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(id).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>());
for (FakeMob mob : mobs) { for (FakeMob mob : mobs) {
mob.despawn(); mob.despawn();
@@ -256,9 +265,11 @@ public class EntityLocationHandler {
private void createFakeMob(int entityId, KLocation location) { private void createFakeMob(int entityId, KLocation location) {
if (!canCreateMob.contains(entityId)) return; 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; if(trackedEntity.isEmpty() || playerEntity.isEmpty()) return;
@@ -281,7 +292,7 @@ public class EntityLocationHandler {
RayCollision collision = new RayCollision(eyeLoc.toVector(), eyeLoc.getDirection()); 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); FakeMob mob = new FakeMob(EntityTypes.SLIME);
List<EntityData<?>> types = new ArrayList<>(); List<EntityData<?>> types = new ArrayList<>();
@@ -298,7 +309,8 @@ public class EntityLocationHandler {
} }
public void processZombie() { public void processZombie() {
List<FakeMob> fakeMobs = getTrackedEntity(data.getBukkitPlayer().getEntityId()) List<FakeMob> fakeMobs = data.getWorldTracker().getCurrentWorld().get()
.getTrackedEntity(data.getBukkitPlayer().getEntityId())
.map(TrackedEntity::getFakeMobs) .map(TrackedEntity::getFakeMobs)
.orElse(new ArrayList<>()); .orElse(new ArrayList<>());
@@ -312,7 +324,7 @@ public class EntityLocationHandler {
RayCollision collision = new RayCollision(eyeLoc.toVector(), eyeLoc.getDirection()); 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); fakeMob.teleport(point.getX(), point.getY(), point.getZ(), 0 ,0);
break; break;
@@ -321,7 +333,8 @@ public class EntityLocationHandler {
} }
public void processFakeMobs(int entityId, boolean rel, double x, double y, double z) { 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(fakeMobs.isEmpty()) {
if(!rel) { if(!rel) {
@@ -3,6 +3,7 @@ package dev.brighten.ac.handler;
import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; 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.protocol.teleport.RelativeFlag;
import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; 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.APlayer;
import dev.brighten.ac.data.obj.CMove; import dev.brighten.ac.data.obj.CMove;
import dev.brighten.ac.utils.*; 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.objects.evicting.EvictingList;
import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.timer.impl.TickTimer;
import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.types.RayCollision; import dev.brighten.ac.utils.world.types.RayCollision;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.val; 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;
import me.hydro.emulator.util.mcp.MathHelper.FastMathType; import me.hydro.emulator.util.mcp.MathHelper.FastMathType;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffectType;
import java.util.*; import java.util.*;
@@ -87,21 +85,14 @@ public class MovementHandler {
private final Timer lastCinematic = new TickTimer(2); private final Timer lastCinematic = new TickTimer(2);
private final Timer lastReset = new TickTimer(2); private final Timer lastReset = new TickTimer(2);
private final EvictingList<Integer> sensitivitySamples = new EvictingList<>(50); private final EvictingList<Integer> sensitivitySamples = new EvictingList<>(50);
private boolean modernMovement; private final boolean modernMovement;
public MovementHandler(APlayer player) { public MovementHandler(APlayer player) {
this.player = player; this.player = player;
Player bplayer = player.getBukkitPlayer();
// Initializing player location // 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.setBox(new SimpleCollisionBox(to.getLoc(), 0.6, 1.8));
to.setOnGround(bplayer.isOnGround()); to.setOnGround(false);
// Setting from as same location as to // Setting from as same location as to
from.setLoc(to); from.setLoc(to);
@@ -123,31 +114,32 @@ public class MovementHandler {
*/ */
final PotionEffect[] EFFECTS = new PotionEffect[3]; final PotionEffect[] EFFECTS = new PotionEffect[3];
for (org.bukkit.potion.PotionEffect potionEffect : player.getPotionHandler().potionEffects) { for (KPotionEffect potionEffect : player.getPotionHandler().getPotionEffects()) {
if (potionEffect.getType().equals(PotionEffectType.SPEED)) { if (potionEffect.potionType().equals(PotionTypes.SPEED)) {
EFFECTS[0] = PotionEffect.builder() EFFECTS[0] = PotionEffect.builder()
.amplifier(potionEffect.getAmplifier()) .amplifier(potionEffect.properties().amplifier())
.type(me.hydro.emulator.util.PotionEffectType.SPEED) .type(me.hydro.emulator.util.PotionEffectType.SPEED)
.build(); .build();
} else if (potionEffect.getType().equals(PotionEffectType.SLOW)) { } else if (potionEffect.potionType().equals(PotionTypes.SLOWNESS)) {
EFFECTS[1] = PotionEffect.builder() EFFECTS[1] = PotionEffect.builder()
.amplifier(potionEffect.getAmplifier()) .amplifier(potionEffect.properties().amplifier())
.type(me.hydro.emulator.util.PotionEffectType.SLOW) .type(me.hydro.emulator.util.PotionEffectType.SLOW)
.build(); .build();
} else if (potionEffect.getType().equals(PotionEffectType.JUMP)) { } else if (potionEffect.potionType().equals(PotionTypes.JUMP_BOOST)) {
EFFECTS[2] = PotionEffect.builder() EFFECTS[2] = PotionEffect.builder()
.amplifier(potionEffect.getAmplifier()) .amplifier(potionEffect.properties().amplifier())
.type(me.hydro.emulator.util.PotionEffectType.JUMP) .type(me.hydro.emulator.util.PotionEffectType.JUMP)
.build(); .build();
} }
} }
if(player.EMULATOR.getTags().contains("003") && !isZeroThree) { if (player.EMULATOR.getTags().contains("003") && !isZeroThree) {
runEmulation(to, true); runEmulation(to, true);
} }
IterationResult minimum = null; IterationResult minimum = null;
iteration: { iteration:
{
for (KLocation posLoc : new ArrayList<>(posLocs)) { for (KLocation posLoc : new ArrayList<>(posLocs)) {
// Resetting to prevent lag issues. // Resetting to prevent lag issues.
@@ -157,7 +149,7 @@ public class MovementHandler {
if (minimum == null || minimum.getOffset() > result.getOffset()) { if (minimum == null || minimum.getOffset() > result.getOffset()) {
minimum = result; minimum = result;
if(minimum.getOffset() < 1E-26) { if (minimum.getOffset() < 1E-26) {
// The player teleported, therefore we don't need to continue with predictions. // The player teleported, therefore we don't need to continue with predictions.
break iteration; break iteration;
} }
@@ -171,96 +163,95 @@ public class MovementHandler {
Motion previousMotion = player.EMULATOR.getMotion().clone(); Motion previousMotion = player.EMULATOR.getMotion().clone();
for (int forward : isZeroThree ? new int[] {0} : FULL_RANGE) { for (int forward : isZeroThree ? new int[]{0} : FULL_RANGE) {
for (int strafe : isZeroThree ? new int[] {0} : FULL_RANGE) { for (int strafe : isZeroThree ? new int[]{0} : FULL_RANGE) {
for (boolean jumping : getJumpingIterations()) { for (boolean jumping : getJumpingIterations()) {
for (boolean sprinting : getSprintingIterations(forward)) { for (boolean sprinting : getSprintingIterations(forward)) {
for (boolean usingItem : getUsingItemIterations(forward, strafe)) { for (boolean usingItem : getUsingItemIterations(forward, strafe)) {
for (boolean hitSlow : getHitSlowIterations()) { for (boolean hitSlow : getHitSlowIterations()) {
for (FastMathType fastMath : getFastMathIterations(forward, strafe)) { for (FastMathType fastMath : getFastMathIterations(forward, strafe)) {
for(Vector3d possibleVector : possibleVelocity) { for (Vector3d possibleVector : possibleVelocity) {
IterationInput input = IterationInput.builder() IterationInput input = IterationInput.builder()
.jumping(jumping) .jumping(jumping)
.forward(forward) .forward(forward)
.strafing(strafe) .strafing(strafe)
.sprinting(sprinting) .sprinting(sprinting)
.usingItem(usingItem) .usingItem(usingItem)
.modernMovement(modernMovement) .modernMovement(modernMovement)
.hitSlowdown(hitSlow) .hitSlowdown(hitSlow)
.aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2) .aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2)
.fastMathType(fastMath) .fastMathType(fastMath)
.sneaking(player.getInfo().isSneaking()) .sneaking(player.getInfo().sneaking)
.ground(from.isOnGround()) .ground(from.isOnGround())
.to(new Vector(to.getX(), to.getY(), to.getZ())) .to(new Vector(to.getX(), to.getY(), to.getZ()))
.yaw(to.getYaw()) .yaw(to.getYaw())
.lastReportedBoundingBox(from.getBox().toNeo()) .lastReportedBoundingBox(from.getBox().toNeo())
.effectSpeed(EFFECTS[0]) .effectSpeed(EFFECTS[0])
.effectSlow(EFFECTS[1]) .effectSlow(EFFECTS[1])
.waitingForTeleport(!posLocs.isEmpty()) .waitingForTeleport(!posLocs.isEmpty())
.effectJump(EFFECTS[2]).build(); .effectJump(EFFECTS[2]).build();
boolean isVelocity = false; boolean isVelocity = false;
if(possibleVector != null) { if (possibleVector != null) {
// Setting the motion to the possible velocity vector. // Setting the motion to the possible velocity vector.
player.EMULATOR.getMotion().setMotionX(possibleVector.getX()); player.EMULATOR.getMotion().setMotionX(possibleVector.getX());
player.EMULATOR.getMotion().setMotionY(possibleVector.getY()); player.EMULATOR.getMotion().setMotionY(possibleVector.getY());
player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ()); player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ());
// Has to be this way because order of operations in the emulator. // Has to be this way because order of operations in the emulator.
isVelocity = true; isVelocity = true;
} else { } else {
// Resetting the motion to the previous motion. // Resetting the motion to the previous motion.
player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX()); player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX());
player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY()); player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY());
player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ()); player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ());
} }
IterationResult result = player.EMULATOR.runIteration(input); IterationResult result = player.EMULATOR.runIteration(input);
if(isVelocity) { if (isVelocity) {
result.getTags().add("velocity"); result.getTags().add("velocity");
} }
if(fastMath == FastMathType.FAST_LEGACY) { if (fastMath == FastMathType.FAST_LEGACY) {
result.getTags().add("fast_legacy"); result.getTags().add("fast_legacy");
} else if(fastMath == FastMathType.VANILLA) { } else if (fastMath == FastMathType.VANILLA) {
result.getTags().add("vanilla"); result.getTags().add("vanilla");
} else if(fastMath == FastMathType.FAST_NEW) { } else if (fastMath == FastMathType.FAST_NEW) {
result.getTags().add("fast_new"); result.getTags().add("fast_new");
} else if(fastMath == FastMathType.MODERN_VANILLA) { } else if (fastMath == FastMathType.MODERN_VANILLA) {
result.getTags().add("modern_vanilla"); result.getTags().add("modern_vanilla");
} }
if(forward > 0) { if (forward > 0) {
result.getTags().add("w-key"); result.getTags().add("w-key");
} else if(forward < 0) { } else if (forward < 0) {
result.getTags().add("s-key"); result.getTags().add("s-key");
} }
if(strafe > 0) { if (strafe > 0) {
result.getTags().add("d-key"); result.getTags().add("d-key");
} else if(strafe < 0) { } else if (strafe < 0) {
result.getTags().add("a-key"); result.getTags().add("a-key");
} }
if (minimum == null || minimum.getOffset() > result.getOffset()) { if (minimum == null || minimum.getOffset() > result.getOffset()) {
minimum = result; minimum = result;
if (minimum.getOffset() < 1E-26) { if (minimum.getOffset() < 1E-26) {
break iteration; break iteration;
}
} }
} }
} }
} }
}
} }
} }
} }
} }
} }
} }
if (minimum != null) {
if(minimum != null) {
predicted = minimum.getPredicted(); predicted = minimum.getPredicted();
double mx = player.EMULATOR.getMotion().getMotionX(); double mx = player.EMULATOR.getMotion().getMotionX();
@@ -269,7 +260,7 @@ public class MovementHandler {
double total = mx * mx + my * my + mz * mz; double total = mx * mx + my * my + mz * mz;
if(total < 9E-4) { if (total < 9E-4) {
player.getInfo().lastCanceledFlying.reset(); player.getInfo().lastCanceledFlying.reset();
minimum.getTags().add("003"); minimum.getTags().add("003");
} }
@@ -282,11 +273,11 @@ public class MovementHandler {
} }
player.EMULATOR.confirm(minimum.getIteration()); player.EMULATOR.confirm(minimum.getIteration());
if(minimum.getTags().contains("003")) { if (minimum.getTags().contains("003")) {
player.EMULATOR.getTags().add("003"); player.EMULATOR.getTags().add("003");
} }
if(minimum.getTags().contains("bad_offset")) { if (minimum.getTags().contains("bad_offset")) {
player.EMULATOR.setLastReportedBoundingBox(getTo().getBox().toNeo()); player.EMULATOR.setLastReportedBoundingBox(getTo().getBox().toNeo());
} }
} }
@@ -294,7 +285,7 @@ public class MovementHandler {
private FastMathType[] getFastMathIterations(int strafe, int forward) { private FastMathType[] getFastMathIterations(int strafe, int forward) {
// Because no movement is being applied, there is no angle calculation being done // 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}; return new FastMathType[]{FastMathType.FAST_LEGACY};
} }
@@ -317,7 +308,9 @@ public class MovementHandler {
private boolean[] getUsingItemIterations(int forward, int strafe) { private boolean[] getUsingItemIterations(int forward, int strafe) {
return (forward == 0 && strafe == 0 || 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() { private boolean[] getJumpingIterations() {
@@ -336,13 +329,13 @@ public class MovementHandler {
&& player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17); && player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17);
checkMovement = teleportsToConfirm == 0 && posLocs.isEmpty(); checkMovement = teleportsToConfirm == 0 && posLocs.isEmpty();
if (checkMovement) { if (checkMovement) {
moveTicks++; moveTicks++;
if (!packet.hasPositionChanged()) moveTicks = 1; if (!packet.hasPositionChanged()) moveTicks = 1;
} else moveTicks = 0; } else moveTicks = 0;
if(excuseNextFlying) { if (excuseNextFlying) {
return; return;
} }
@@ -359,10 +352,10 @@ public class MovementHandler {
if (moveTicks > 0) { if (moveTicks > 0) {
// Updating block locations // Updating block locations
player.getInfo().setBlockOnTo(Optional.of(player.getBlockUpdateHandler() player.getInfo().setBlockOnTo(Optional.of(player.getWorldTracker()
.getBlock(new IntVector(to.getLoc())))); .getBlock(to.getLoc().toVector3i())));
player.getInfo().setBlockBelow(Optional.of(player.getBlockUpdateHandler() player.getInfo().setBlockBelow(Optional.of(player.getWorldTracker()
.getBlock(new IntVector(to.getLoc().clone().subtract(0, 1, 0))))); .getBlock(to.getLoc().clone().subtract(0, 1, 0).clone().toVector3i())));
if (packet.hasPositionChanged()) { if (packet.hasPositionChanged()) {
// Updating player bounding box // Updating player bounding box
@@ -486,7 +479,7 @@ public class MovementHandler {
player.getInfo().setWasOnSlime(player.getBlockInfo().onSlime); player.getInfo().setWasOnSlime(player.getBlockInfo().onSlime);
groundTicks++; groundTicks++;
airTicks = 0; airTicks = 0;
player.getInfo().groundJumpBoost = player.getPotionHandler().getEffectByType(PotionEffectType.JUMP); player.getInfo().groundJumpBoost = player.getPotionHandler().getEffectByType(PotionTypes.JUMP_BOOST);
} else { } else {
player.getInfo().groundJumpBoost = Optional.empty(); player.getInfo().groundJumpBoost = Optional.empty();
airTicks++; airTicks++;
@@ -503,7 +496,7 @@ public class MovementHandler {
.anyMatch(capability -> capability.canFly)); .anyMatch(capability -> capability.canFly));
boolean hasLevitation = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9) 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().setRiptiding(CompatHandler.getINSTANCE().isRiptiding(player.getBukkitPlayer()));
player.getInfo().setGliding(CompatHandler.getINSTANCE().isGliding(player.getBukkitPlayer())); player.getInfo().setGliding(CompatHandler.getINSTANCE().isGliding(player.getBukkitPlayer()));
@@ -570,7 +563,7 @@ it
// generate a method that processes velocityHistory and compares to current deltaY. // generate a method that processes velocityHistory and compares to current deltaY.
private void processVelocity() { private void processVelocity() {
//Iterate through player.getInfo().getVelocityHistory() and compare to current deltaY. //Iterate through player.getInfo().getVelocityHistory() and compare to current deltaY.
if(player.getInfo().isDoingVelocity()) { if (player.getInfo().isDoingVelocity()) {
player.getInfo().getVelocity().reset(); player.getInfo().getVelocity().reset();
} }
synchronized (player.getInfo().getVelocityHistory()) { synchronized (player.getInfo().getVelocityHistory()) {
@@ -590,22 +583,22 @@ it
} }
private void processBotMove(WrapperPlayClientPlayerFlying packet) { private void processBotMove(WrapperPlayClientPlayerFlying packet) {
if(player.getMob() == null) return; if (player.getMob() == null) return;
if (packet.hasPositionChanged() || packet.hasRotationChanged()) { if (packet.hasPositionChanged() || packet.hasRotationChanged()) {
KLocation origin = to.getLoc().clone().add(0, 1.7, 0); 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))); final double MULTIPLIER = Math.max(-0.5, Math.min(-1, -1 / (Math.abs(deltaYaw) * 0.25)));
RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection() 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)) { if (player.getInfo().botAttack.isNotPassed(7)) {
loc1.setY(Math.max(origin.getY() + 2, loc1.getY())); loc1.setY(Math.max(origin.getY() + 2, loc1.getY()));
player.getMob().teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch()); player.getMob().teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch());
} else { } else {
loc1.setY(Math.max(origin.getY() + 0.6, loc1.getY())); 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() Anticheat.INSTANCE.getRunUtils().taskLaterAsync(() -> player.getMob()
.teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch()), 5); .teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch()), 5);
} }
@@ -661,7 +654,7 @@ it
public void runPositionHackFix() { public void runPositionHackFix() {
if (sentPositionUpdate) return; 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)); relFlags));
player.getBukkitPlayer().sendMessage("§c[Anticheat] §7Position update sent to fix movement issues."); player.getBukkitPlayer().sendMessage("§c[Anticheat] §7Position update sent to fix movement issues.");
@@ -725,10 +718,10 @@ it
packet.getYaw(), packet.getPitch()); packet.getYaw(), packet.getPitch());
if (packet.getRelativeFlags().has(RelativeFlag.X)) { 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)) { 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)) { if (packet.getRelativeFlags().has(RelativeFlag.Z)) {
loc.add(0, 0, player.getMovement().getTo().getLoc().getZ()); loc.add(0, 0, player.getMovement().getTo().getLoc().getZ());
@@ -743,7 +736,6 @@ it
teleportsToConfirm++; teleportsToConfirm++;
loc.setTimeStamp(System.currentTimeMillis()); loc.setTimeStamp(System.currentTimeMillis());
player.runKeepaliveAction(ka -> { player.runKeepaliveAction(ka -> {
teleportsToConfirm--; teleportsToConfirm--;
@@ -762,7 +754,7 @@ it
* *
* @param location Location * @param location Location
*/ */
public void moveTo(Location location) { public void moveTo(KLocation location) {
KLocation newLoc = new KLocation(location); KLocation newLoc = new KLocation(location);
to.getLoc().setLocation(newLoc); to.getLoc().setLocation(newLoc);
to.getLoc().setLocation(newLoc); to.getLoc().setLocation(newLoc);
@@ -814,7 +806,7 @@ it
* @param packet WrapperPlayClientPlayerFlyingh * @param packet WrapperPlayClientPlayerFlyingh
*/ */
private void setTo(WrapperPlayClientPlayerFlying packet) { private void setTo(WrapperPlayClientPlayerFlying packet) {
to.setWorld(player.getBukkitPlayer().getWorld()); to.setWorld(player.getWorldTracker().getCurrentWorld().get());
if (packet.hasPositionChanged()) { if (packet.hasPositionChanged()) {
to.getLoc().setX(packet.getLocation().getX()); to.getLoc().setX(packet.getLocation().getX());
to.getLoc().setY(packet.getLocation().getY()); to.getLoc().setY(packet.getLocation().getY());
@@ -18,6 +18,8 @@ import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import dev.brighten.ac.Anticheat; import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer; 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.FakeMob;
import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.packet.PlayerCapabilities; 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.BlockUtils;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.MovementUtils; import dev.brighten.ac.utils.MovementUtils;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import lombok.val; import lombok.val;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import java.util.Optional; import java.util.Optional;
@@ -38,13 +37,14 @@ public class PacketHandler {
public boolean processReceive(APlayer player, PacketReceiveEvent event) { public boolean processReceive(APlayer player, PacketReceiveEvent event) {
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
Object wrapped; 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); TransactionClientWrapper packet = new TransactionClientWrapper(event);
wrapped = packet; wrapped = packet;
if(packet.getId() == 0) { if (packet.getId() == 0) {
if (Anticheat.INSTANCE.getKeepaliveProcessor().keepAlives.get(packet.getAction()) != null) { if (Anticheat.INSTANCE.getKeepaliveProcessor().keepAlives.get(packet.getAction()) != null) {
Anticheat.INSTANCE.getKeepaliveProcessor().addResponse(player, packet.getAction()); Anticheat.INSTANCE.getKeepaliveProcessor().addResponse(player, packet.getAction());
@@ -68,7 +68,7 @@ public class PacketHandler {
synchronized (player.instantTransaction) { synchronized (player.instantTransaction) {
var iterator = player.instantTransaction.keySet().iterator(); var iterator = player.instantTransaction.keySet().iterator();
while(iterator.hasNext()) { while (iterator.hasNext()) {
Short key = iterator.next(); Short key = iterator.next();
if (key > ka.id) { if (key > ka.id) {
@@ -96,7 +96,7 @@ public class PacketHandler {
synchronized (player.keepAliveLock) { synchronized (player.keepAliveLock) {
player.keepAliveStamps.removeIf(action -> { player.keepAliveStamps.removeIf(action -> {
if(action.stamp > ka.id) { if (action.stamp > ka.id) {
return false; return false;
} }
@@ -110,10 +110,17 @@ public class PacketHandler {
Optional.ofNullable(player.instantTransaction.remove(packet.getAction())) Optional.ofNullable(player.instantTransaction.remove(packet.getAction()))
.ifPresent(t -> t.two.accept(t.one)); .ifPresent(t -> t.two.accept(t.one));
} }
} else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) } else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_INPUT)) {
|| event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION) WrapperPlayClientPlayerInput packet = new WrapperPlayClientPlayerInput(event);
|| event.getPacketType().equals(PacketType.Play.Client.PLAYER_ROTATION)
|| event.getPacketType().equals(PacketType.Play.Client.PLAYER_FLYING)) { 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); WrapperPlayClientPlayerFlying packet = new WrapperPlayClientPlayerFlying(event);
wrapped = packet; wrapped = packet;
if (player.getMovement().isExcuseNextFlying()) { if (player.getMovement().isExcuseNextFlying()) {
@@ -127,7 +134,7 @@ public class PacketHandler {
player.getLagInfo().setLastFlying(timestamp); player.getLagInfo().setLastFlying(timestamp);
player.getEntityLocationHandler().onFlying(); player.getEntityTrackHandler().onFlying();
if (player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17) if (player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17)
&& packet.hasPositionChanged() && packet.hasRotationChanged() && packet.hasPositionChanged() && packet.hasRotationChanged()
@@ -145,17 +152,17 @@ public class PacketHandler {
player.getVelocityHandler().onFlyingPost(packet); player.getVelocityHandler().onFlyingPost(packet);
return result; 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); WrapperPlayClientSteerVehicle packet = new WrapperPlayClientSteerVehicle(event);
wrapped = packet; wrapped = packet;
// Check for isUnmount() // Check for isUnmount()
if (player.getBukkitPlayer().isInsideVehicle() && packet.isUnmount()) { if (player.getInfo().isInVehicle() && packet.isUnmount()) {
player.getInfo().getVehicleSwitch().reset(); player.getInfo().getVehicleSwitch().reset();
player.getInfo().setInVehicle(false); 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); WrapperPlayClientEntityAction packet = new WrapperPlayClientEntityAction(event);
wrapped = packet; wrapped = packet;
@@ -178,13 +185,13 @@ public class PacketHandler {
break; break;
} }
case START_FLYING_WITH_ELYTRA: { case START_FLYING_WITH_ELYTRA: {
if(player.isGlidePossible()) { if (player.isGlidePossible()) {
player.getInfo().setGliding(true); player.getInfo().setGliding(true);
} }
break; 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); WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event);
wrapped = packet; wrapped = packet;
@@ -192,39 +199,44 @@ public class PacketHandler {
FakeMob mob = Anticheat.INSTANCE.getFakeTracker().getEntityById(packet.getEntityId()); FakeMob mob = Anticheat.INSTANCE.getFakeTracker().getEntityById(packet.getEntityId());
if (packet.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) { if (packet.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) {
if (player.hitsToCancel > 0) {
player.hitsToCancel--;
cancel = true;
}
if (mob != null) { if (mob != null) {
player.getEntityLocationHandler().getTargetOfFakeMob(mob.getEntityId()) player.getEntityTrackHandler().getTargetOfFakeMob(mob.getEntityId())
.ifPresent(targetId -> { .ifPresent(targetId -> {
player.getEntityLocationHandler().removeFakeMob(targetId); player.getEntityTrackHandler().removeFakeMob(targetId);
player.getInfo().lastFakeBotHit.reset(); player.getInfo().lastFakeBotHit.reset();
}); });
if (player.getMob().getEntityId() == packet.getEntityId()) { if (player.getMob().getEntityId() == packet.getEntityId()) {
player.getInfo().botAttack.reset(); player.getInfo().botAttack.reset();
} }
} else { } 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) { 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(); 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); WrapperPlayClientAnimation packet = new WrapperPlayClientAnimation(event);
wrapped = packet; wrapped = packet;
if(packet.getHand() == InteractionHand.MAIN_HAND) { if (packet.getHand() == InteractionHand.MAIN_HAND) {
long delta = timestamp - player.getInfo().lastArmSwing; long delta = timestamp - player.getInfo().lastArmSwing;
player.getInfo().cps.add(1000D / delta, timestamp); player.getInfo().cps.add(1000D / delta, timestamp);
player.getInfo().lastArmSwing = 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); WrapperPlayClientPlayerBlockPlacement packet = new WrapperPlayClientPlayerBlockPlacement(event);
wrapped = packet; wrapped = packet;
@@ -236,19 +248,19 @@ public class PacketHandler {
// Used item // Used item
if (pos.getX() == -1 && (pos.getY() == 255 | pos.getY() == -1) && pos.getZ() == -1 if (pos.getX() == -1 && (pos.getY() == 255 | pos.getY() == -1) && pos.getZ() == -1
&& stack.isPresent() && stack.isPresent()
&& BlockUtils.isUsable(SpigotConversionUtil.toBukkitItemMaterial(stack.get().getType()))) { && BlockUtils.isUsable(player.getPlayerVersion(), stack.get().getType())) {
player.getInfo().getLastUseItem().reset(); player.getInfo().getLastUseItem().reset();
} }
player.getBlockUpdateHandler().onPlace(packet); player.getWorldTracker().onPlace(packet);
} else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_DIGGING)) { } else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_DIGGING)) {
WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event); WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event);
wrapped = packet; wrapped = packet;
player.getInfo().getLastBlockDig().reset(); player.getInfo().getLastBlockDig().reset();
player.getBlockUpdateHandler().onDig(packet); player.getWorldTracker().onDig(packet);
} else if(event.getPacketType().equals(PacketType.Play.Client.CLIENT_STATUS)) { } else if (event.getPacketType().equals(PacketType.Play.Client.CLIENT_STATUS)) {
WrapperPlayClientClientStatus packet = new WrapperPlayClientClientStatus(event); WrapperPlayClientClientStatus packet = new WrapperPlayClientClientStatus(event);
wrapped = packet; wrapped = packet;
@@ -258,10 +270,10 @@ public class PacketHandler {
player.getInfo().lastInventoryOpen.reset(); player.getInfo().lastInventoryOpen.reset();
return false; 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); wrapped = new WrapperPlayClientCloseWindow(event);
player.getInfo().setInventoryOpen(false); 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); WrapperPlayClientPluginMessage packet = new WrapperPlayClientPluginMessage(event);
wrapped = packet; wrapped = packet;
@@ -286,7 +298,7 @@ public class PacketHandler {
+ ": " + wrapped); + ": " + wrapped);
} }
return player.getCheckHandler().callSyncPacket(wrapped, timestamp); return cancel || player.getCheckHandler().callSyncPacket(wrapped, timestamp);
} }
public boolean processSend(APlayer player, PacketSendEvent event) { public boolean processSend(APlayer player, PacketSendEvent event) {
@@ -309,30 +321,36 @@ public class PacketHandler {
player.getInfo().getPossibleCapabilities().clear(); player.getInfo().getPossibleCapabilities().clear();
} }
}, true); }, 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) { } else if(event.getPacketType() == PacketType.Play.Server.BLOCK_CHANGE) {
WrapperPlayServerBlockChange packet = new WrapperPlayServerBlockChange(event); WrapperPlayServerBlockChange packet = new WrapperPlayServerBlockChange(event);
wrapped = packet; wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet); player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.MULTI_BLOCK_CHANGE) { } else if(event.getPacketType() == PacketType.Play.Server.MULTI_BLOCK_CHANGE) {
WrapperPlayServerMultiBlockChange packet = new WrapperPlayServerMultiBlockChange(event); WrapperPlayServerMultiBlockChange packet = new WrapperPlayServerMultiBlockChange(event);
wrapped = packet; wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet); player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.CHUNK_DATA) { } else if(event.getPacketType() == PacketType.Play.Server.CHUNK_DATA) {
WrapperPlayServerChunkData packet = new WrapperPlayServerChunkData(event); WrapperPlayServerChunkData packet = new WrapperPlayServerChunkData(event);
wrapped = packet; wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet); player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.MAP_CHUNK_BULK) { } else if(event.getPacketType() == PacketType.Play.Server.MAP_CHUNK_BULK) {
WrapperPlayServerChunkDataBulk packet = new WrapperPlayServerChunkDataBulk(event); WrapperPlayServerChunkDataBulk packet = new WrapperPlayServerChunkDataBulk(event);
wrapped = packet; wrapped = packet;
player.getBlockUpdateHandler().runUpdate(packet); player.getWorldTracker().runUpdate(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) {
WrapperPlayServerEntityEffect packet = new WrapperPlayServerEntityEffect(event); WrapperPlayServerEntityEffect packet = new WrapperPlayServerEntityEffect(event);
@@ -394,18 +412,19 @@ public class PacketHandler {
} else if(event.getPacketType() == PacketType.Play.Server.RESPAWN) { } else if(event.getPacketType() == PacketType.Play.Server.RESPAWN) {
wrapped = new WrapperPlayServerRespawn(event); wrapped = new WrapperPlayServerRespawn(event);
if(player.getPlayerVersion().isOlderThan(ClientVersion.V_1_14)) { 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.runKeepaliveAction(ka -> player.getBlockUpdateHandler() player.getInfo().lastRespawn.reset();
.setMinHeight(player.getDimensionType())); player.getInfo().setPose(Pose.STANDING);
});
player.runKeepaliveAction(ka -> player.getWorldTracker()
.onRespawn((WrapperPlayServerRespawn) wrapped));
} else if(event.getPacketType() == PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) { } else if(event.getPacketType() == PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) {
WrapperPlayServerPlayerPositionAndLook packet = new WrapperPlayServerPlayerPositionAndLook(event); WrapperPlayServerPlayerPositionAndLook packet = new WrapperPlayServerPlayerPositionAndLook(event);
wrapped = packet; wrapped = packet;
player.runKeepaliveAction(ka ->
player.getBlockUpdateHandler().setMinHeight(player.getDimensionType()));
player.getMovement().addPosition(packet); player.getMovement().addPosition(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) { } else if(event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) {
WrapperPlayServerAttachEntity packet = new WrapperPlayServerAttachEntity(event); WrapperPlayServerAttachEntity packet = new WrapperPlayServerAttachEntity(event);
@@ -423,37 +442,37 @@ public class PacketHandler {
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onEntityDestroy(packet); player.getEntityTrackHandler().onEntityDestroy(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) {
WrapperPlayServerEntityTeleport packet = new WrapperPlayServerEntityTeleport(event); WrapperPlayServerEntityTeleport packet = new WrapperPlayServerEntityTeleport(event);
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onTeleportSent(packet); player.getEntityTrackHandler().onTeleportSent(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_MOVEMENT) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_MOVEMENT) {
WrapperPlayServerEntityMovement packet = new WrapperPlayServerEntityMovement(event); WrapperPlayServerEntityMovement packet = new WrapperPlayServerEntityMovement(event);
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) {
WrapperPlayServerEntityRelativeMove packet = new WrapperPlayServerEntityRelativeMove(event); WrapperPlayServerEntityRelativeMove packet = new WrapperPlayServerEntityRelativeMove(event);
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) {
WrapperPlayServerEntityRotation packet = new WrapperPlayServerEntityRotation(event); WrapperPlayServerEntityRotation packet = new WrapperPlayServerEntityRotation(event);
wrapped = packet; 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) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION) {
WrapperPlayServerEntityRelativeMoveAndRotation packet = new WrapperPlayServerEntityRelativeMoveAndRotation(event); WrapperPlayServerEntityRelativeMoveAndRotation packet = new WrapperPlayServerEntityRelativeMoveAndRotation(event);
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) { } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event); WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
wrapped = packet; wrapped = packet;
@@ -462,7 +481,7 @@ public class PacketHandler {
double y = packet.getPosition().getY(); double y = packet.getPosition().getY();
double z = packet.getPosition().getZ(); 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 TrackedEntity(packet.getEntityId(), packet.getEntityType(),
new KLocation(x, y, z, packet.getYaw(), packet.getPitch()))); new KLocation(x, y, z, packet.getYaw(), packet.getPitch())));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) { } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
@@ -474,7 +493,7 @@ public class PacketHandler {
double y = packet.getPosition().getY(); double y = packet.getPosition().getY();
double z = packet.getPosition().getZ(); 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 TrackedEntity(packet.getEntityId(), packet.getEntityType(),
new KLocation(x, y, z, packet.getYaw(), packet.getPitch()))); new KLocation(x, y, z, packet.getYaw(), packet.getPitch())));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) { } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) {
@@ -487,7 +506,7 @@ public class PacketHandler {
double z = packet.getPosition().getZ(); 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 TrackedEntity(packet.getEntityId(), EntityTypes.PLAYER,
new KLocation(x, y, z, packet.getYaw(),packet.getPitch()))); new KLocation(x, y, z, packet.getYaw(),packet.getPitch())));
} else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) { } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) {
@@ -499,14 +518,14 @@ public class PacketHandler {
int y = packet.getPosition().getY(); int y = packet.getPosition().getY();
int z = packet.getPosition().getZ(); 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))); new TrackedEntity(packet.getEntityId(), EntityTypes.PAINTING, new KLocation(x, y, z)));
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_POSITION_SYNC) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_POSITION_SYNC) {
WrapperPlayServerEntityPositionSync packet = new WrapperPlayServerEntityPositionSync(event); WrapperPlayServerEntityPositionSync packet = new WrapperPlayServerEntityPositionSync(event);
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onPositionSync(packet); player.getEntityTrackHandler().onPositionSync(packet);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) { } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) {
wrapped = new WrapperPlayServerEntityMetadata(event); wrapped = new WrapperPlayServerEntityMetadata(event);
}else if(event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) { }else if(event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) {
@@ -514,7 +533,7 @@ public class PacketHandler {
wrapped = packet; wrapped = packet;
player.getEntityLocationHandler().onEntityDestroy(packet); player.getEntityTrackHandler().onEntityDestroy(packet);
} else if(event.getPacketType() == PacketType.Play.Server.CLOSE_WINDOW) { } else if(event.getPacketType() == PacketType.Play.Server.CLOSE_WINDOW) {
wrapped = new WrapperPlayServerCloseWindow(event); wrapped = new WrapperPlayServerCloseWindow(event);
player.runKeepaliveAction(ka -> player.getInfo().setInventoryOpen(false)); player.runKeepaliveAction(ka -> player.getInfo().setInventoryOpen(false));
@@ -1,59 +1,118 @@
package dev.brighten.ac.handler; 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.client.WrapperPlayClientPlayerFlying;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect;
import dev.brighten.ac.data.APlayer; 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 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.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class PotionHandler { public class PotionHandler {
private final APlayer data; 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; 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) { public void onFlying(WrapperPlayClientPlayerFlying packet) {
for (PotionEffect effect : potionEffects) { lock.readLock().lock();
if(data.getBukkitPlayer().hasPotionEffect(effect.getType())) continue; 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) { public void onPotionEffect(WrapperPlayServerEntityEffect packet) {
data.runKeepaliveAction(d -> { data.runKeepaliveAction(d -> {
var type = SpigotConversionUtil.toBukkitPotionEffectType(packet.getPotionType()); var type = packet.getPotionType();
data.getPotionHandler().potionEffects.stream().filter(pe -> pe.getType().equals(type)) lock.writeLock().lock();
.forEach(data.getPotionHandler().potionEffects::remove); try {
data.getPotionHandler().potionEffects data.getPotionHandler().potionEffects.removeIf(pe -> pe.potionType().equals(type));
.add(new PotionEffect(type, packet.getEffectDurationTicks(), packet.getEffectAmplifier(), data.getPotionHandler().potionEffects
packet.isAmbient())); .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) { public boolean hasPotionEffect(PotionType type) {
for (PotionEffect potionEffect : potionEffects) { lock.readLock().lock();
if(potionEffect.getType().equals(type)) try {
return true; 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) { public Optional<KPotionEffect> getEffectByType(PotionType type) {
for (PotionEffect potionEffect : potionEffects) { lock.readLock().lock();
if(potionEffect.getType().equals(type)) try {
return Optional.of(potionEffect); 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,67 +1,68 @@
package dev.brighten.ac.handler.block; package dev.brighten.ac.handler.block;
import com.github.retrooper.packetevents.PacketEvents; 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.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.BaseChunk;
import com.github.retrooper.packetevents.protocol.world.chunk.Column; 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.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.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d; 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.WrapperPlayClientPlayerBlockPlacement;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; 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.*;
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 dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.BlockUtils; import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.Materials; 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 dev.brighten.ac.utils.world.types.RayCollision;
import io.github.retrooper.packetevents.util.SpigotConversionUtil; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.Chunk; import java.util.ArrayList;
import org.bukkit.Location; import java.util.HashMap;
import org.bukkit.Material; import java.util.Map;
import org.bukkit.World; import java.util.concurrent.atomic.AtomicReference;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@Slf4j @Slf4j
@SuppressWarnings("unused") @SuppressWarnings("unused")
@RequiredArgsConstructor @RequiredArgsConstructor
public class BlockUpdateHandler { public class BlockUpdateHandler {
// Array dimensions: 64×64 covers a render distance of up to 32 chunks without
// collision. Index = (chunkX & MASK) * SIZE + (chunkZ & MASK); stored KColumn
// x/z are chunk coordinates and are validated on every lookup.
private static final int CHUNK_ARRAY_BITS = 6; // 2^6 = 64 per axis
private static final int CHUNK_ARRAY_SIZE = 1 << CHUNK_ARRAY_BITS; // 64
private static final int CHUNK_ARRAY_MASK = CHUNK_ARRAY_SIZE - 1; // 63
private final KColumn[] chunks = new KColumn[CHUNK_ARRAY_SIZE * CHUNK_ARRAY_SIZE];
private final APlayer player; private final APlayer player;
private final Map<String, World> worlds = new HashMap<>();
@Getter
private AtomicReference<World> currentWorld = new AtomicReference<>();
/** /**
* Clear all chunks when the player changes worlds * Clear all chunks when the player changes worlds
*/ */
public void onWorldChange() { public void onRespawn(WrapperPlayServerRespawn respawn) {
synchronized (chunks) { respawn.getWorldName()
java.util.Arrays.fill(chunks, null); .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)));
} }
/** /**
@@ -72,25 +73,30 @@ public class BlockUpdateHandler {
public void onPlace(WrapperPlayClientPlayerBlockPlacement place) { public void onPlace(WrapperPlayClientPlayerBlockPlacement place) {
player.getInfo().lastBlockUpdate.reset(); player.getInfo().lastBlockUpdate.reset();
// Could not possibly be a block placement as it's not a block a player is holding. // 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 // Some dumbass shit I have to do because Minecraft with Lilypads
if (place.getItemStack().isPresent() if (place.getItemStack().isPresent()
&& BlockUtils.getXMaterial(place.getItemStack().get().getType()).equals(XMaterial.LILY_PAD)) { && place.getItemStack().get().getType().equals(ItemTypes.LILY_PAD)) {
RayCollision rayCollision = new RayCollision(player.getBukkitPlayer().getEyeLocation().toVector(), RayCollision rayCollision = new RayCollision(player.getMovement().getTo().getLoc()
player.getBukkitPlayer().getLocation().getDirection()); .add(0, player.getEyeHeight(), 0).toVector(),
player.getMovement().getTo().getLoc().getDirection());
//TODO Refactor this system to use just packetevents instead of this class
WrappedBlock block = rayCollision.getClosestBlockOfType(player, Materials.LIQUID, 5); WrappedBlock block = rayCollision.getClosestBlockOfType(player, Materials.LIQUID, 5);
if (block != null) { 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; } else return;
} // Not an actual block place, just an interact } // Not an actual block place, just an interact
else if (pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) { else if (pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) {
return; return;
} else { } else {
pos.setX(pos.getX() + place.getFace().getModX()); pos = pos.with(pos.getX() + place.getFace().getModX(),
pos.setY(pos.getY() + place.getFace().getModY()); pos.getY() + place.getFace().getModY(),
pos.setZ(pos.getZ() + place.getFace().getModZ()); pos.getZ() + place.getFace().getModZ());
} }
player.getInfo().getLastPlace().reset(); player.getInfo().getLastPlace().reset();
@@ -100,220 +106,16 @@ public class BlockUpdateHandler {
int y = pos.getY(); int y = pos.getY();
int z = pos.getZ(); int z = pos.getZ();
var placedType = place.getItemStack().get().getType().getPlacedType(); if(place.getItemStack().isEmpty() || place.getItemStack().get().getType().getPlacedType() == null) {
if(place.getItemStack().isEmpty() || placedType == null) {
return; return;
} }
updateBlock(x, y, z, WrappedBlockState.getDefaultState(placedType)); currentWorld.get().updateBlock(x, y, z,
WrappedBlockState.getDefaultState(place.getItemStack().get().getType().getPlacedType()));
} }
/** static final WrappedBlockState airBlockState = WrappedBlockState
* Keep track of block diggings since the Bukkit API will be a bit behind .getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), 0);
* @param x x coordinate
* @param z z coordinate
* @return the chunk at the specified coordinates
*/
public KColumn getChunk(int x, int z) {
int chunkX = x >> 4;
int chunkZ = z >> 4;
synchronized (chunks) {
int index = chunkIndex(chunkX, chunkZ);
KColumn chunk = chunks[index];
// Validate that the stored entry belongs to this chunk position
if (chunk == null || chunk.x() != chunkX || chunk.z() != chunkZ) {
chunk = getBukkitColumn(player.getBukkitPlayer().getWorld(), x, z);
if (chunk == null) {
return new KColumn(chunkX, chunkZ, new BaseChunk[maxHeight / 16]);
}
chunks[index] = chunk;
}
return chunk;
}
}
private static int chunkIndex(int chunkX, int chunkZ) {
return (chunkX & CHUNK_ARRAY_MASK) * CHUNK_ARRAY_SIZE + (chunkZ & CHUNK_ARRAY_MASK);
}
private KColumn getBukkitColumn(World world, int x, int z) {
int chunkX = x >> 4;
int chunkZ = z >> 4;
Chunk chunk = BlockUtils.getChunkAsync(world, chunkX, chunkZ).orElse(null);
if(chunk == null) {
// Handle loading on main thread
Anticheat.INSTANCE.getRunUtils().task(() -> {
int index = chunkIndex(chunkX, chunkZ);
synchronized (chunks) {
KColumn existing = chunks[index];
if (existing == null || existing.x() != chunkX || existing.z() != chunkZ) {
KColumn loaded = getBukkitColumn(world, x, z);
if (loaded != null) {
chunks[index] = loaded;
}
}
}
});
return null;
}
BaseChunk[] levels = new BaseChunk[world.getMaxHeight() / 16];
for(int i = 0; i < levels.length; i++) {
levels[i] = create();
}
int chunkBlockX = chunk.getX() * 16;
int chunkBlockZ = chunk.getZ() * 16;
for(int blockX = chunkBlockX; blockX < chunkBlockX + 16 ; blockX++) {
for(int blockZ = chunkBlockZ; blockZ < chunkBlockZ + 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(chunkX, chunkZ, levels);
}
private void updateChunk(Column chunk) {
synchronized (chunks) {
int index = chunkIndex(chunk.getX(), chunk.getZ());
chunks[index] = new KColumn(chunk.getX(), chunk.getZ(), chunk.getChunks());
}
}
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());
}
/** /**
* Keep track of block breaking since the Bukkit API will be a bit behind. * Keep track of block breaking since the Bukkit API will be a bit behind.
@@ -324,13 +126,13 @@ public class BlockUpdateHandler {
player.getInfo().lastBlockUpdate.reset(); player.getInfo().lastBlockUpdate.reset();
if (dig.getAction() == DiggingAction.FINISHED_DIGGING) { 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) { if (pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) {
return; return;
} }
updateBlock(pos.getX(), pos.getY(), pos.getZ(), airBlockState); currentWorld.get().updateBlock(pos.getX(), pos.getY(), pos.getZ(), airBlockState);
} }
} }
@@ -343,9 +145,9 @@ public class BlockUpdateHandler {
// Updating block information // Updating block information
player.runKeepaliveAction(k -> { 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());
}); });
} }
@@ -358,41 +160,20 @@ public class BlockUpdateHandler {
player.runKeepaliveAction(k -> { player.runKeepaliveAction(k -> {
for (WrapperPlayServerMultiBlockChange.EncodedBlock info : packet.getBlocks()) { 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. * Keep track of block updates since the Bukkit API will be a bit behind.
* @param chunkUpdate Wrapped PacketPlayOutMapChunk * @param chunkUpdate Wrapped PacketPlayOutMapChunk
*/ */
public void runUpdate(WrapperPlayServerChunkData chunkUpdate) { public void runUpdate(WrapperPlayServerChunkData chunkUpdate) {
player.runKeepaliveAction(k -> updateChunk(chunkUpdate.getColumn())); player.runKeepaliveAction(k -> currentWorld.get().updateChunk(chunkUpdate.getColumn()));
} }
public void runUpdate(WrapperPlayServerChunkDataBulk chunkBulk) { public void runUpdate(WrapperPlayServerChunkDataBulk chunkBulk) {
@@ -403,9 +184,10 @@ public class BlockUpdateHandler {
int x = chunkBulk.getX()[index]; int x = chunkBulk.getX()[index];
int z = chunkBulk.getZ()[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);
} }
}); });
} }
@@ -418,8 +200,8 @@ public class BlockUpdateHandler {
* @param modZ the z modifier * @param modZ the z modifier
* @return the block relative to the specified location * @return the block relative to the specified location
*/ */
public WrappedBlock getRelative(IntVector location, int modX, int modY, int modZ) { public WrappedBlock getRelative(Vector3i location, int modX, int modY, int modZ) {
return getBlock(location.clone().add(modX, modY, modZ)); return currentWorld.get().getBlock(location.add(modX, modY, modZ));
} }
/** /**
@@ -429,7 +211,7 @@ public class BlockUpdateHandler {
* @param distance the distance * @param distance the distance
* @return the block relative to the specified location * @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, return getRelative(location,
face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance); face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance);
} }
@@ -440,8 +222,20 @@ public class BlockUpdateHandler {
* @param face the face * @param face the face
* @return the block relative to the specified location * @return the block relative to the specified location
*/ */
public WrappedBlock getRelative(IntVector location, BlockFace face) { public WrappedBlock getRelative(Vector3i location, BlockFace face) {
return getBlock(location.clone().add(face.getModX(), face.getModY(), face.getModZ())); 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) {} public record KColumn(int x, int z, BaseChunk[] chunks) {}
@@ -1,9 +1,11 @@
package dev.brighten.ac.handler.block; 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.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -17,7 +19,7 @@ public class Chunk {
* @param location - Location of the block * @param location - Location of the block
* @return Optional of the block at the specified location * @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()); return getBlockAt(location.getX(), location.getY(), location.getZ());
} }
@@ -64,7 +66,18 @@ public class Chunk {
* @param location - Location of the block * @param location - Location of the block
* @param block - Block to update to * @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); 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,186 @@
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 it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
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;
// Array dimensions: 64×64 covers a render distance of up to 32 chunks without
// collision. Index = (chunkX & MASK) * SIZE + (chunkZ & MASK); stored KColumn
// x/z are chunk coordinates and are validated on every lookup.
private static final int CHUNK_ARRAY_BITS = 6; // 2^6 = 64 per axis
private static final int CHUNK_ARRAY_SIZE = 1 << CHUNK_ARRAY_BITS; // 64
private static final int CHUNK_ARRAY_MASK = CHUNK_ARRAY_SIZE - 1; // 63
private final BlockUpdateHandler.KColumn[] chunks = new BlockUpdateHandler.KColumn[CHUNK_ARRAY_SIZE * CHUNK_ARRAY_SIZE];
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) {
int chunkX = x >> 4;
int chunkZ = z >> 4;
synchronized (chunks) {
int index = chunkIndex(chunkX, chunkZ);
BlockUpdateHandler.KColumn chunk = chunks[index];
// Validate that the stored entry belongs to this chunk position
if (chunk == null || chunk.x() != chunkX || chunk.z() != chunkZ) {
chunk = new BlockUpdateHandler.KColumn(chunkX, chunkZ, new BaseChunk[maxHeight / 16]);
chunks[index] = chunk;
}
return chunk;
}
}
private static int chunkIndex(int chunkX, int chunkZ) {
return ((chunkX & CHUNK_ARRAY_MASK) << CHUNK_ARRAY_BITS) | (chunkZ & CHUNK_ARRAY_MASK);
}
void updateChunk(Column chunk) {
synchronized (chunks) {
int index = chunkIndex(chunk.getX(), chunk.getZ());
chunks[index] = new BlockUpdateHandler.KColumn(chunk.getX(), chunk.getZ(), chunk.getChunks());
}
}
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;
if(col == null) {
return new WrappedBlock(new Vector3i(x, y, z),
StateTypes.AIR,
BlockUpdateHandler.airBlockState);
}
BaseChunk chunk = col.chunks().length - 1 < (y >> 4) ? null : col.chunks()[Math.max(0, (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.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; 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.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class WrappedBlock { public class WrappedBlock {
private IntVector location; private Vector3i location;
private StateType type; private StateType type;
private WrappedBlockState blockState; private WrappedBlockState blockState;
} }
@@ -1,13 +1,19 @@
package dev.brighten.ac.handler.entity; 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.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.EntityLocation;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
@Getter @Getter
@Setter @Setter
@@ -17,6 +23,8 @@ public class TrackedEntity {
private KLocation location; private KLocation location;
private EntityLocation oldEntityLocation, newEntityLocation; private EntityLocation oldEntityLocation, newEntityLocation;
private List<FakeMob> fakeMobs = new ArrayList<>(); 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) { public TrackedEntity(int entityId, EntityType entityType, KLocation location) {
this.entityId = entityId; this.entityId = entityId;
@@ -31,4 +39,30 @@ public class TrackedEntity {
newEntityLocation.yaw = location.getYaw(); newEntityLocation.yaw = location.getYaw();
newEntityLocation.pitch = location.getPitch(); 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), double dh = Math.min(value.getMovement().getDeltaXZ(), 1),
dy = Math.min(1, Math.abs(value.getMovement().getDeltaY())); 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() .stream()
.filter(te -> .filter(te ->
te.getLocation().distance(value.getMovement().getTo().getLoc()) < (2 + (dh + dy) / 2)) te.getLocation().distance(value.getMovement().getTo().getLoc()) < (2 + (dh + dy) / 2))
@@ -1,25 +1,8 @@
package dev.brighten.ac.handler.protocol; package dev.brighten.ac.handler.protocol;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.handler.protocol.impl.NoAPI; import dev.brighten.ac.data.APlayer;
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;
public interface Protocol { public interface Protocol {
int getPlayerVersion(Player player); int getPlayerVersion(APlayer 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();
}
}
} }
@@ -1,13 +1,13 @@
package dev.brighten.ac.handler.protocol.impl; package dev.brighten.ac.handler.protocol.impl;
import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.PacketEvents;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.protocol.Protocol; import dev.brighten.ac.handler.protocol.Protocol;
import org.bukkit.entity.Player;
public class NoAPI implements Protocol { public class NoAPI implements Protocol {
@Override @Override
public int getPlayerVersion(Player player) { public int getPlayerVersion(APlayer player) {
return PacketEvents.getAPI().getPlayerManager().getClientVersion(player).getProtocolVersion(); return PacketEvents.getAPI().getPlayerManager().getClientVersion(player.getBukkitPlayer()).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 com.viaversion.viaversion.api.Via;
import dev.brighten.ac.Anticheat; import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.protocol.Protocol; import dev.brighten.ac.handler.protocol.Protocol;
import org.bukkit.entity.Player;
public class ViaVersionAPI implements Protocol { public class ViaVersionAPI implements Protocol {
@Override @Override
public int getPlayerVersion(Player player) { public int getPlayerVersion(APlayer player) {
Anticheat.INSTANCE.alog("Getting player version for " + player.getName()); Anticheat.INSTANCE.alog("Getting player version for " + player.getBukkitPlayer().getName());
var toReturn = Via.getAPI().getPlayerVersion(player.getUniqueId()); var toReturn = Via.getAPI().getPlayerVersion(player.getBukkitPlayer().getUniqueId());
Anticheat.INSTANCE.alog("Player version for " + player.getName() + " is " + toReturn); Anticheat.INSTANCE.alog("Player version for " + player.getBukkitPlayer().getName() + " is " + toReturn);
return toReturn; return toReturn;
} }
@@ -1,5 +1,6 @@
package dev.brighten.ac.listener; package dev.brighten.ac.listener;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.Anticheat; import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
@@ -68,14 +69,15 @@ public class GeneralListener implements Listener {
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId()) Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId())
.ifPresent(player -> { .ifPresent(player -> {
player.getBlockUpdateHandler().onWorldChange();
// Updating bot loc when changing worlds // Updating bot loc when changing worlds
Location origin = event.getTo().clone().add(0, 1.7, 0); 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(() -> { Anticheat.INSTANCE.getRunUtils().taskLater(() -> {
player.getMob().despawn(); player.getMob().despawn();
@@ -1,6 +1,7 @@
package dev.brighten.ac.utils; package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.protocol.world.Direction; 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.RayCollision;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location; import org.bukkit.Location;
@@ -211,6 +212,14 @@ public class AxisAlignedBB {
return rayTrace(origin, dir); 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) { public Vec3D rayTrace(Vec3D vec3d, Vec3D vec3d1) {
Vec3D vec3d2 = vec3d.a(vec3d1, this.minX); Vec3D vec3d2 = vec3d.a(vec3d1, this.minX);
Vec3D vec3d3 = vec3d.a(vec3d1, this.maxX); 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.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.item.type.ItemType; 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.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; 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.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.handler.entity.TrackedEntity;
import dev.brighten.ac.utils.math.IntVector;
import io.github.retrooper.packetevents.util.SpigotConversionUtil; import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Vehicle;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.EnumSet; import java.util.EnumSet;
@@ -84,20 +83,20 @@ public class BlockUtils {
return Optional.empty(); return Optional.empty();
} }
public static Optional<WrappedBlock> getRelative(APlayer player, IntVector location, int modX, int modY, int modZ) { public static Optional<WrappedBlock> getRelative(APlayer player, Vector3i location, int modX, int modY, int modZ) {
return Optional.of(player.getBlockUpdateHandler() return Optional.of(player.getWorldTracker()
.getRelative(new IntVector(location.getX(), location.getY(), location.getZ()), .getRelative(new Vector3i(location.getX(), location.getY(), location.getZ()),
modX, modY, modZ)); 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 com.github.retrooper.packetevents.protocol.world
.BlockFace face, int distance) { .BlockFace face, int distance) {
return getRelative(player, location, return getRelative(player, location,
face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance); 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, return getRelative(player, vector,
face.getModX(), face.getModY(), face.getModZ()); face.getModX(), face.getModY(), face.getModZ());
} }
@@ -134,6 +133,12 @@ public class BlockUtils {
return isUsable(getXMaterial(material)); 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) { public static boolean isUsable(XMaterial xmaterial) {
if(XEDIBLE.contains(xmaterial)) return true; if(XEDIBLE.contains(xmaterial)) return true;
return switch (xmaterial) { return switch (xmaterial) {
@@ -1,16 +1,15 @@
package dev.brighten.ac.utils; 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.Particle;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; 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.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3f; import com.github.retrooper.packetevents.util.Vector3f;
import com.github.retrooper.packetevents.util.Vector3i;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerParticle; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerParticle;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.entity.TrackedEntity; 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.BlockData;
import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.EntityData;
@@ -137,8 +136,8 @@ public class Helper {
for (int x = x1; x < x2; ++x) for (int x = x1; x < x2; ++x)
for (int y = y1 - 1; y < y2; ++y) for (int y = y1 - 1; y < y2; ++y)
for (int z = z1; z < z2; ++z) { for (int z = z1; z < z2; ++z) {
IntVector vec = new IntVector(x, y, z); Vector3i vec = new Vector3i(x, y, z);
StateType type = player.getBlockUpdateHandler().getBlock(vec).getType(); StateType type = player.getWorldTracker().getBlock(vec).getType();
if (type != StateTypes.AIR && (mask == -100 || Materials.checkFlag(type, mask))) { if (type != StateTypes.AIR && (mask == -100 || Materials.checkFlag(type, mask))) {
CollisionBox box = BlockData.getData(type) 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);
}
}
@@ -9,6 +9,7 @@ import org.bukkit.Material;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
//TODO Refactor this system to use just packetevents instead of this class
public class Materials { public class Materials {
private static final Map<StateType, Integer> MATERIAL_FLAGS = new HashMap<>(); private static final Map<StateType, Integer> MATERIAL_FLAGS = new HashMap<>();
@@ -31,11 +32,11 @@ public class Materials {
int flag = MATERIAL_FLAGS.getOrDefault(mat, 0); int flag = MATERIAL_FLAGS.getOrDefault(mat, 0);
//We use the one in BlockUtils also since we can't trust Material to include everything. //We use the one in BlockUtils also since we can't trust Material to include everything.
if (mat.isSolid() || mat.getName().contains("COMPARATOR") || mat.getName().contains("DIODE")) { if (mat.isSolid() || mat.getName().contains("COMPARATOR") || mat.getName().contains("DIODE") || mat.isBlocking()) {
flag |= SOLID; flag |= SOLID;
} }
if(!(BlockData.getData(mat).getDefaultBox() instanceof NoCollisionBox)) { if(!(BlockData.getData(mat).getDefaultBox() instanceof NoCollisionBox) || mat.isBlocking()) {
flag |= COLLIDABLE; flag |= COLLIDABLE;
} }
@@ -58,7 +58,7 @@ public class MiscUtils {
for(int x = startX ; x < endX ; x++) { for(int x = startX ; x < endX ; x++) {
for(int y = startY ; y < endY ; y++) { for(int y = startY ; y < endY ; y++) {
for(int z = startZ ; z < endZ ; z++) { 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)) if(Materials.checkFlag(type, bitmask))
return true; return true;
@@ -19,7 +19,7 @@ public class MovementUtils {
public static double getJumpHeight(APlayer data) { public static double getJumpHeight(APlayer data) {
float baseHeight = 0.42f; 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; .orElse(0) * 0.1f;
return baseHeight; return baseHeight;
@@ -38,7 +38,7 @@ public class MovementUtils {
int i = MathHelper.floor_double(data.getMovement().getTo().getLoc().getX()); int i = MathHelper.floor_double(data.getMovement().getTo().getLoc().getX());
int j = MathHelper.floor_double(data.getMovement().getTo().getBox().minY); int j = MathHelper.floor_double(data.getMovement().getTo().getBox().minY);
int k = MathHelper.floor_double(data.getMovement().getTo().getLoc().getZ()); 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); return Materials.checkFlag(block.getType(), Materials.LADDER);
@@ -54,6 +54,10 @@ public class IntVector implements Cloneable {
return new Vector(x, y, z); return new Vector(x, y, z);
} }
public Vector3i toVector3i() {
return new Vector3i(x, y, z);
}
@Override @Override
public String toString() { public String toString() {
return "[" + x + ", " + y + ", " + z + "]"; 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.PacketEvents;
import com.github.retrooper.packetevents.manager.server.ServerVersion; 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 dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Effect; import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.util.Vector;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -15,15 +18,15 @@ public class RayTrace {
//origin = start position //origin = start position
//direction = direction in which the raytrace will go //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.origin = origin;
this.direction = direction; this.direction = direction;
} }
//general intersection detection //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()) { if (position.getX() < min.getX() || position.getX() > max.getX()) {
return false; return false;
} else if (position.getY() < min.getY() || position.getY() > max.getY()) { } 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 //get a point on the raytrace at X blocks away
public Vector getPostion(double blocksAway) { public Vector3d getPostion(double blocksAway) {
return origin.clone().add(direction.clone().multiply(blocksAway)); return origin.add(direction.multiply(blocksAway));
} }
//checks if a position is on contained within the position //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(); 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 //get all postions on a raytrace
public List<Vector> traverse(double blocksAway, double accuracy) { public List<Vector3d> traverse(double blocksAway, double accuracy) {
List<Vector> positions = new ArrayList<>(); List<Vector3d> positions = new ArrayList<>();
for (double d = 0; d <= blocksAway; d += accuracy) { for (double d = 0; d <= blocksAway; d += accuracy) {
positions.add(getPostion(d)); positions.add(getPostion(d));
} }
return positions; return positions;
} }
public List<Vector> traverse(double skip, double blocksAway, double accuracy) { public List<Vector3d> traverse(double skip, double blocksAway, double accuracy) {
List<Vector> positions = new ArrayList<>(); List<Vector3d> positions = new ArrayList<>();
for (double d = skip; d <= blocksAway; d += accuracy) { for (double d = skip; d <= blocksAway; d += accuracy) {
positions.add(getPostion(d)); positions.add(getPostion(d));
} }
@@ -62,14 +65,17 @@ public class RayTrace {
public List<Block> getBlocks(World world, double blocksAway, double accuracy) { public List<Block> getBlocks(World world, double blocksAway, double accuracy) {
List<Block> blocks = new ArrayList<>(); 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; return blocks;
} }
//intersection detection for current raytrace with return //intersection detection for current raytrace with return
public Vector positionOfIntersection(Vector min, Vector max, double blocksAway, double accuracy) { public Vector3d positionOfIntersection(Vector3d min, Vector3d max, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy); List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) { for (Vector3d position : positions) {
if (intersects(position, min, max)) { if (intersects(position, min, max)) {
return position; return position;
} }
@@ -78,9 +84,9 @@ public class RayTrace {
} }
//intersection detection for current raytrace //intersection detection for current raytrace
public boolean intersects(Vector min, Vector max, double blocksAway, double accuracy) { public boolean intersects(Vector3d min, Vector3d max, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy); List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) { for (Vector3d position : positions) {
if (intersects(position, min, max)) { if (intersects(position, min, max)) {
return true; return true;
} }
@@ -89,9 +95,9 @@ public class RayTrace {
} }
//bounding blockbox instead of vector //bounding blockbox instead of vector
public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) { public Vector3d positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy); List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) { for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) { if (intersects(position, collisionBox.min(), collisionBox.max())) {
return position; return position;
} }
@@ -99,9 +105,9 @@ public class RayTrace {
return null; return null;
} }
public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) { public Vector3d positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector> positions = traverse(skip, blocksAway, accuracy); List<Vector3d> positions = traverse(skip, blocksAway, accuracy);
for (Vector position : positions) { for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) { if (intersects(position, collisionBox.min(), collisionBox.max())) {
return position; return position;
} }
@@ -111,8 +117,8 @@ public class RayTrace {
//bounding blockbox instead of vector //bounding blockbox instead of vector
public boolean intersects(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) { public boolean intersects(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy); List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) { for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) { if (intersects(position, collisionBox.min(), collisionBox.max())) {
return true; return true;
} }
@@ -121,8 +127,8 @@ public class RayTrace {
} }
public boolean intersects(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) { public boolean intersects(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) {
List<Vector> positions = traverse(blocksAway, accuracy); List<Vector3d> positions = traverse(blocksAway, accuracy);
for (Vector position : positions) { for (Vector3d position : positions) {
if (intersects(position, collisionBox.min(), collisionBox.max())) { if (intersects(position, collisionBox.min(), collisionBox.max())) {
return true; return true;
} }
@@ -132,8 +138,8 @@ public class RayTrace {
//debug / effects //debug / effects
public void highlight(World world, double blocksAway, double accuracy) { public void highlight(World world, double blocksAway, double accuracy) {
for (Vector position : traverse(blocksAway, accuracy)) { for (Vector3d position : traverse(blocksAway, accuracy)) {
world.playEffect(position.toLocation(world), (PacketEvents.getAPI().getServerManager().getVersion() 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); .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.enums.*;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; 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.protocol.world.states.type.StateTypes;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.BlockUtils; 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.blocks.*;
import dev.brighten.ac.utils.world.types.*; import dev.brighten.ac.utils.world.types.*;
@@ -110,12 +110,58 @@ public enum BlockData {
_DOOR(new DoorHandler(), BlockTags.DOORS.getStates().toArray(new StateType[0])), _DOOR(new DoorHandler(), BlockTags.DOORS.getStates().toArray(new StateType[0])),
_HOPPER(new HopperBounding(), StateTypes.HOPPER), _HOPPER((version, player, block) -> {
if(version.isOlderThan(ClientVersion.V_1_13)) {
double thickness = 0.125;
return new ComplexCollisionBox(
new SimpleCollisionBox(0,0,0,1, 0.125*5,1),
new SimpleCollisionBox(0, 0.125*5, 0, thickness, 1, 1),
new SimpleCollisionBox(1-thickness, 0.125*5, 0, 1, 1, 1),
new SimpleCollisionBox(0, 0.125*5, 0, 1, 1, thickness),
new SimpleCollisionBox(0, 0.125*5, 1-thickness, 1, 1, 1)
);
} else {
ComplexCollisionBox hopperBox = new ComplexCollisionBox();
switch (block.getBlockState().getFacing()) {
case DOWN:
hopperBox.add(new HexCollisionBox(6.0D, 0.0D, 6.0D, 10.0D, 4.0D, 10.0D));
break;
case EAST:
hopperBox.add(new HexCollisionBox(12.0D, 4.0D, 6.0D, 16.0D, 8.0D, 10.0D));
break;
case NORTH:
hopperBox.add(new HexCollisionBox(6.0D, 4.0D, 0.0D, 10.0D, 8.0D, 4.0D));
break;
case SOUTH:
hopperBox.add(new HexCollisionBox(6.0D, 4.0D, 12.0D, 10.0D, 8.0D, 16.0D));
break;
case WEST:
hopperBox.add(new HexCollisionBox(0.0D, 4.0D, 6.0D, 4.0D, 8.0D, 10.0D));
break;
}
hopperBox.add(new SimpleCollisionBox(0, 0.625, 0, 1.0, 0.6875, 1.0));
hopperBox.add(new SimpleCollisionBox(0, 0.6875, 0, 0.125, 1, 1));
hopperBox.add(new SimpleCollisionBox(0.125, 0.6875, 0, 1, 1, 0.125));
hopperBox.add(new SimpleCollisionBox(0.125, 0.6875, 0.875, 1, 1, 1));
hopperBox.add(new SimpleCollisionBox(0.25, 0.25, 0.25, 0.75, 0.625, 0.75));
hopperBox.add(new SimpleCollisionBox(0.875, 0.6875, 0.125, 1, 1, 0.875));
return hopperBox;
}
}, StateTypes.HOPPER),
_CAKE((protocol, player, block) -> { _CAKE((protocol, player, block) -> {
double f1 = (1 + block.getBlockState().getBites() * 2) / 16D; double f1 = (1 + block.getBlockState().getBites() * 2) / 16D;
return new SimpleCollisionBox(f1, 0, 0.0625, 1 - 0.0625, 0.5, 1 - 0.0625); return new SimpleCollisionBox(f1, 0, 0.0625, 1 - 0.0625, 0.5, 1 - 0.0625);
}, StateTypes.CAKE), }, StateTypes.CAKE),
STONE_CUTTER((version, player, block) -> {
if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2))
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1);
return new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 9.0D, 16.0D);
}, StateTypes.STONECUTTER),
_COCOA_BEAN((protocol, player, block) -> { _COCOA_BEAN((protocol, player, block) -> {
int age = block.getBlockState().getAge(); int age = block.getBlockState().getAge();
if (protocol.isNewerThanOrEquals(ClientVersion.V_1_9_1) && protocol.isOlderThan(ClientVersion.V_1_11)) if (protocol.isNewerThanOrEquals(ClientVersion.V_1_9_1) && protocol.isOlderThan(ClientVersion.V_1_11))
@@ -282,7 +328,34 @@ public enum BlockData {
StateTypes.STRUCTURE_VOID), StateTypes.STRUCTURE_VOID),
_END_ROD(new DynamicRod(), StateTypes.END_ROD), _END_ROD(new DynamicRod(), StateTypes.END_ROD),
_CAULDRON(new CouldronBounding(), StateTypes.CAULDRON), _CAULDRON((version, player, block) -> {
if(version.isOlderThanOrEquals(ClientVersion.V_1_13_2)) {
double thickness = 0.125;
return new ComplexCollisionBox(new SimpleCollisionBox(0,0,0,1, 0.3125,1),
new SimpleCollisionBox(0, 0.3125, 0, thickness, 1, 1),
new SimpleCollisionBox(1-thickness, 0.3125, 0, 1, 1, 1),
new SimpleCollisionBox(0, 0.3125, 0, 1, 1, thickness),
new SimpleCollisionBox(0, 0.3125, 1-thickness, 1, 1, 1));
} else {
return new ComplexCollisionBox(new SimpleCollisionBox(0.0, 0.0, 0.0, 0.125, 1.0, 0.25),
new SimpleCollisionBox(0.0, 0.0, 0.75, 0.125, 1.0, 1.0),
new SimpleCollisionBox(0.125, 0.0, 0.0, 0.25, 1.0, 0.125),
new SimpleCollisionBox(0.125, 0.0, 0.875, 0.25, 1.0, 1.0),
new SimpleCollisionBox(0.75, 0.0, 0.0, 1.0, 1.0, 0.125),
new SimpleCollisionBox(0.75, 0.0, 0.875, 1.0, 1.0, 1.0),
new SimpleCollisionBox(0.875, 0.0, 0.125, 1.0, 1.0, 0.25),
new SimpleCollisionBox(0.875, 0.0, 0.75, 1.0, 1.0, 0.875),
new SimpleCollisionBox(0.0, 0.1875, 0.25, 1.0, 0.25, 0.75),
new SimpleCollisionBox(0.125, 0.1875, 0.125, 0.875, 0.25, 0.25),
new SimpleCollisionBox(0.125, 0.1875, 0.75, 0.875, 0.25, 0.875),
new SimpleCollisionBox(0.25, 0.1875, 0.0, 0.75, 1.0, 0.125),
new SimpleCollisionBox(0.25, 0.1875, 0.875, 0.75, 1.0, 1.0),
new SimpleCollisionBox(0.0, 0.25, 0.25, 0.125, 1.0, 0.75),
new SimpleCollisionBox(0.875, 0.25, 0.25, 1.0, 1.0, 0.75)
);
}
}, StateTypes.CAULDRON),
_CACTUS(new SimpleCollisionBox(0.0625, 0, 0.0625, _CACTUS(new SimpleCollisionBox(0.0625, 0, 0.0625,
1 - 0.0625, 1 - 0.0625, 1 - 0.0625), StateTypes.CACTUS), 1 - 0.0625, 1 - 0.0625, 1 - 0.0625), StateTypes.CACTUS),
_PISTON_BASE(new PistonBaseCollision(), StateTypes.PISTON, StateTypes.STICKY_PISTON), _PISTON_BASE(new PistonBaseCollision(), StateTypes.PISTON, StateTypes.STICKY_PISTON),
@@ -304,6 +377,67 @@ public enum BlockData {
}, StateTypes.LECTERN), }, StateTypes.LECTERN),
_POT(new SimpleCollisionBox(0.3125, 0.0, 0.3125, 0.6875, 0.375, 0.6875), _POT(new SimpleCollisionBox(0.3125, 0.0, 0.3125, 0.6875, 0.375, 0.6875),
StateTypes.FLOWER_POT), StateTypes.FLOWER_POT),
KELP(new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 9.0D, 16.0D), StateTypes.KELP),
// Kelp block is a full block, so it by default is correct
BELL((version, player, block) -> {
if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2))
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1);
BlockFace direction = block.getBlockState().getFacing();
if (block.getBlockState().getAttachment() == Attachment.FLOOR) {
return direction != BlockFace.NORTH && direction != BlockFace.SOUTH ?
new HexCollisionBox(4.0D, 0.0D, 0.0D, 12.0D, 16.0D, 16.0D) :
new HexCollisionBox(0.0D, 0.0D, 4.0D, 16.0D, 16.0D, 12.0D);
}
ComplexCollisionBox complex = new ComplexCollisionBox(
new HexCollisionBox(5.0D, 6.0D, 5.0D, 11.0D, 13.0D, 11.0D),
new HexCollisionBox(4.0D, 4.0D, 4.0D, 12.0D, 6.0D, 12.0D));
if (block.getBlockState().getAttachment() == Attachment.CEILING) {
complex.add(new HexCollisionBox(7.0D, 13.0D, 7.0D, 9.0D, 16.0D, 9.0D));
} else if (block.getBlockState().getAttachment() == Attachment.DOUBLE_WALL) {
if (direction != BlockFace.NORTH && direction != BlockFace.SOUTH) {
complex.add(new HexCollisionBox(0.0D, 13.0D, 7.0D, 16.0D, 15.0D, 9.0D));
} else {
complex.add(new HexCollisionBox(7.0D, 13.0D, 0.0D, 9.0D, 15.0D, 16.0D));
}
} else if (direction == BlockFace.NORTH) {
complex.add(new HexCollisionBox(7.0D, 13.0D, 0.0D, 9.0D, 15.0D, 13.0D));
} else if (direction == BlockFace.SOUTH) {
complex.add(new HexCollisionBox(7.0D, 13.0D, 3.0D, 9.0D, 15.0D, 16.0D));
} else {
if (direction == BlockFace.EAST) {
complex.add(new HexCollisionBox(3.0D, 13.0D, 7.0D, 16.0D, 15.0D, 9.0D));
} else {
complex.add(new HexCollisionBox(0.0D, 13.0D, 7.0D, 13.0D, 15.0D, 9.0D));
}
}
return complex;
}, StateTypes.BELL),
SCAFFOLDING((version, player, block) -> {
// ViaVersion replacement block - hay block
if (version.isOlderThanOrEquals(ClientVersion.V_1_13_2))
return new SimpleCollisionBox(0, 0, 0, 1, 1, 1);
if (player.getMovement().getFrom().getY() > player.getMovement().getTo().getY() + 1 - 1e-5 && !player.getInfo().sneaking) {
return new ComplexCollisionBox(new HexCollisionBox(0.0D, 14.0D, 0.0D, 16.0D, 16.0D, 16.0D),
new HexCollisionBox(0.0D, 0.0D, 0.0D, 2.0D, 16.0D, 2.0D),
new HexCollisionBox(14.0D, 0.0D, 0.0D, 16.0D, 16.0D, 2.0D),
new HexCollisionBox(0.0D, 0.0D, 14.0D, 2.0D, 16.0D, 16.0),
new HexCollisionBox(14.0D, 0.0D, 14.0D, 16.0D, 16.0D, 16.0D));
}
return block.getBlockState().getDistance() != 0 && block.getBlockState().isBottom() && player.getMovement().getFrom().getY() > player.getMovement().getTo().getY() - 1e-5 ?
new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 2.0D, 16.0D) :
NoCollisionBox.INSTANCE;
}, StateTypes.SCAFFOLDING),
_NONE(NoCollisionBox.INSTANCE, Stream.of(StateTypes.TORCH, StateTypes.REDSTONE_TORCH, _NONE(NoCollisionBox.INSTANCE, Stream.of(StateTypes.TORCH, StateTypes.REDSTONE_TORCH,
StateTypes.REDSTONE_WIRE, StateTypes.REDSTONE_WALL_TORCH, StateTypes.POWERED_RAIL, StateTypes.WALL_TORCH, StateTypes.REDSTONE_WIRE, StateTypes.REDSTONE_WALL_TORCH, StateTypes.POWERED_RAIL, StateTypes.WALL_TORCH,
@@ -361,10 +495,10 @@ public enum BlockData {
return getBox(player, block.getLocation(), version); 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) if (this.box != null)
return this.box.copy().offset(block.getX(), block.getY(), block.getZ()); 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()); .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.PacketEvents;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import dev.brighten.ac.handler.entity.TrackedEntity; 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.NoCollisionBox;
import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox;
import org.bukkit.Location; import org.bukkit.Location;
@@ -23,6 +24,10 @@ public class EntityData {
return bounds(entity.getEntityType()).offset(location.getX(), location.getY(), location.getZ()); 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) { public static CollisionBox getEntityBox(Location location, EntityType entity) {
return bounds(entity).offset(location.getX(), location.getY(), location.getZ()); 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.WrappedBlockState;
import com.github.retrooper.packetevents.protocol.world.states.enums.Half; 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.protocol.world.states.enums.Hinge;
import com.github.retrooper.packetevents.util.Vector3i;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock; 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.CollisionBox;
import dev.brighten.ac.utils.world.types.CollisionFactory; import dev.brighten.ac.utils.world.types.CollisionFactory;
import dev.brighten.ac.utils.world.types.HexCollisionBox; 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) if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2)
|| version.isOlderThanOrEquals(ClientVersion.V_1_12_2)) { || version.isOlderThanOrEquals(ClientVersion.V_1_12_2)) {
if (door.getBlockState().getHalf() == Half.LOWER) { if (door.getBlockState().getHalf() == Half.LOWER) {
IntVector aboveVec = door.getLocation().clone(); Vector3i aboveVec = door.getLocation();
aboveVec.setY(aboveVec.getY() + 1); aboveVec = aboveVec.add(0, aboveVec.getY() + 1, 0);
WrappedBlockState above = player.getBlockUpdateHandler().getBlock(aboveVec).getBlockState(); WrappedBlockState above = player.getWorldTracker().getBlock(aboveVec).getBlockState();
facingDirection = door.getBlockState().getFacing(); facingDirection = door.getBlockState().getFacing();
isClosed = !door.getBlockState().isOpen(); isClosed = !door.getBlockState().isOpen();
@@ -67,10 +67,10 @@ public class DoorHandler implements CollisionFactory {
isRightHinge = false; isRightHinge = false;
} }
} else { } else {
IntVector belowVec = door.getLocation().clone(); Vector3i belowVec = door.getLocation();
belowVec.setY(belowVec.getY() - 1); belowVec = belowVec.add(0, belowVec.getY() - 1, 0);
WrappedBlockState below = player.getBlockUpdateHandler().getBlock(belowVec).getBlockState(); WrappedBlockState below = player.getWorldTracker().getBlock(belowVec).getBlockState();
if (below.getType() == door.getBlockState().getType() && below.getHalf() == Half.LOWER) { if (below.getType() == door.getBlockState().getType() && below.getHalf() == Half.LOWER) {
isClosed = !below.isOpen(); isClosed = !below.isOpen();
@@ -44,7 +44,7 @@ public class DynamicStair implements CollisionFactory {
z = originalStairs.getLocation().getZ(); z = originalStairs.getLocation().getZ();
WrappedBlock offsetOne = player == null WrappedBlock offsetOne = player == null
? null ? null
: player.getBlockUpdateHandler().getBlock( : player.getWorldTracker().getBlock(
x + facing.getModX(), x + facing.getModX(),
y + facing.getModY(), y + facing.getModY(),
z + facing.getModZ()); 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(), .getBlock(x + facing.getOppositeFace().getModX(),
y + facing.getOppositeFace().getModY(), z y + facing.getOppositeFace().getModY(), z
+ facing.getOppositeFace().getModZ()); + 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.particle.type.ParticleType;
import com.github.retrooper.packetevents.protocol.player.ClientVersion; 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.StateType;
import com.github.retrooper.packetevents.util.Vector3d;
import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock; 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.Helper;
import dev.brighten.ac.utils.KLocation;
import dev.brighten.ac.utils.Materials; import dev.brighten.ac.utils.Materials;
import dev.brighten.ac.utils.Tuple; import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.math.RayTrace; import dev.brighten.ac.utils.math.RayTrace;
import dev.brighten.ac.utils.world.BlockData; import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.CollisionBox;
import me.hydro.emulator.util.mcp.MathHelper; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -58,15 +58,15 @@ public class RayCollision implements CollisionBox {
directionZ = 0; directionZ = 0;
} }
public RayCollision(LivingEntity e) { public RayCollision(TrackedEntity e) {
this(e.getEyeLocation()); this(e.getEyeLocation());
} }
public RayCollision(Location l) { public RayCollision(KLocation l) {
this(l.toVector(),l.getDirection()); this(l.toVector(),l.getDirection());
} }
public RayCollision(Vector position, Vector direction) { public RayCollision(Vector3d position, Vector3d direction) {
this.originX = position.getX(); this.originX = position.getX();
this.originY = position.getY(); this.originY = position.getY();
this.originZ = position.getZ(); this.originZ = position.getZ();
@@ -75,17 +75,17 @@ public class RayCollision implements CollisionBox {
this.directionZ = direction.getZ(); this.directionZ = direction.getZ();
} }
public Vector getOrigin() { public Vector3d getOrigin() {
return new Vector(originX, originY, originZ); return new Vector3d(originX, originY, originZ);
} }
public Vector getDirection() { public Vector3d getDirection() {
return new Vector(directionX, directionY, directionZ); return new Vector3d(directionX, directionY, directionZ);
} }
@Override @Override
public boolean isCollided(CollisionBox other) { public boolean isCollided(CollisionBox other) {
if (other instanceof RayCollision) { if (other instanceof RayCollision) {
return false; // lol no support return false; // lol no support
} else { } else {
List<SimpleCollisionBox> boxes = new ArrayList<>(); List<SimpleCollisionBox> boxes = new ArrayList<>();
@@ -141,7 +141,7 @@ public class RayCollision implements CollisionBox {
public List<CollisionBox> boxesOnRay(APlayer player, double distance) { public List<CollisionBox> boxesOnRay(APlayer player, double distance) {
int amount = Math.round((float) (distance / 0.5)); 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<>(); List<CollisionBox> boxes = new ArrayList<>();
ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); 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 fy = MathHelper.floor_double(originY + (directionY * ix));
int fz = MathHelper.floor_double(originZ + (directionZ * 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; if (block == null) continue;
@@ -173,7 +173,7 @@ public class RayCollision implements CollisionBox {
public WrappedBlock getClosestBlockOfType(APlayer player, int bitmask, double distance) { public WrappedBlock getClosestBlockOfType(APlayer player, int bitmask, double distance) {
int amount = Math.round((float) (distance / 0.5)); 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(); ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
for (int i = 0; i < locs.length; i++) { 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 fy = MathHelper.floor_double(originY + (directionY * ix));
int fz = MathHelper.floor_double(originZ + (directionZ * 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; 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()); 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); 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<>(); Tuple<Double, Double> p = new Tuple<>();
if (box==null||!intersect(this,box,p)) if (box==null||!intersect(this,box,p))
return null; return null;
Vector vector = new Vector(directionX,directionY,directionZ); Vector3d vector = new Vector3d(directionX,directionY,directionZ);
vector.normalize(); vector.normalize();
vector.multiply(p.one); vector.multiply(p.one);
vector.add(new Vector(originX,originY,originZ)); vector.add(new Vector3d(originX,originY,originZ));
return vector; return vector;
} }
public Vector collisionPoint(double dist) { public Vector3d collisionPoint(double dist) {
Vector vector = new Vector(directionX,directionY,directionZ); Vector3d vector = new Vector3d(directionX,directionY,directionZ);
vector.normalize(); vector.normalize();
vector.multiply(dist); vector.multiply(dist);
vector.add(new Vector(originX,originY,originZ)); vector.add(new Vector3d(originX,originY,originZ));
return vector; return vector;
} }
} }
@@ -1,6 +1,7 @@
package dev.brighten.ac.utils.world.types; package dev.brighten.ac.utils.world.types;
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; 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.data.APlayer;
import dev.brighten.ac.utils.Helper; import dev.brighten.ac.utils.Helper;
import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.KLocation;
@@ -54,7 +55,7 @@ public class SimpleCollisionBox implements CollisionBox {
maxZ = width / 2; 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()); this(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ());
} }
@@ -76,6 +77,13 @@ public class SimpleCollisionBox implements CollisionBox {
maxY += height; 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() { public void sort() {
double temp; double temp;
if (minX >= maxX) { if (minX >= maxX) {
@@ -196,26 +204,26 @@ public class SimpleCollisionBox implements CollisionBox {
return this; return this;
} }
public Vector[] corners() { public Vector3d[] corners() {
sort(); sort();
Vector[] vectors = new Vector[8]; Vector3d[] vectors = new Vector3d[8];
vectors[0] = new Vector(minX, minY, minZ); vectors[0] = new Vector3d(minX, minY, minZ);
vectors[1] = new Vector(minX, minY, maxZ); vectors[1] = new Vector3d(minX, minY, maxZ);
vectors[2] = new Vector(maxX, minY, minZ); vectors[2] = new Vector3d(maxX, minY, minZ);
vectors[3] = new Vector(maxX, minY, maxZ); vectors[3] = new Vector3d(maxX, minY, maxZ);
vectors[4] = new Vector(minX, maxY, minZ); vectors[4] = new Vector3d(minX, maxY, minZ);
vectors[5] = new Vector(minX, maxY, maxZ); vectors[5] = new Vector3d(minX, maxY, maxZ);
vectors[6] = new Vector(maxX, maxY, minZ); vectors[6] = new Vector3d(maxX, maxY, minZ);
vectors[7] = new Vector(maxX, maxY, maxZ); vectors[7] = new Vector3d(maxX, maxY, maxZ);
return vectors; return vectors;
} }
public Vector min() { public Vector3d min() {
return new Vector(minX, minY, minZ); return new Vector3d(minX, minY, minZ);
} }
public Vector max() { public Vector3d max() {
return new Vector(maxX, maxY, maxZ); return new Vector3d(maxX, maxY, maxZ);
} }
@Override @Override
@@ -1,11 +1,11 @@
package dev.brighten.ac.utils; 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.Vector3d;
import com.github.retrooper.packetevents.util.Vector3i;
import lombok.Data; import lombok.Data;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.util.Vector;
import org.joml.Vector2d;
import java.util.Objects; import java.util.Objects;
@@ -41,14 +41,18 @@ public class KLocation implements Cloneable {
this.timeStamp = System.currentTimeMillis(); 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.x = vector.getX();
this.y = vector.getY(); this.y = vector.getY();
this.z = vector.getZ(); this.z = vector.getZ();
this.timeStamp = System.currentTimeMillis(); this.timeStamp = System.currentTimeMillis();
} }
public KLocation(Location location) { public KLocation(KLocation location) {
this.x = location.getX(); this.x = location.getX();
this.y = location.getY(); this.y = location.getY();
this.z = location.getZ(); this.z = location.getZ();
@@ -57,12 +61,12 @@ public class KLocation implements Cloneable {
this.timeStamp = System.currentTimeMillis(); this.timeStamp = System.currentTimeMillis();
} }
public Vector toVector() { public Vector3d toVector() {
return new Vector(x, y, z); return new Vector3d(x, y, z);
} }
public Vector3d toVector3d() { public Vector3i toVector3i() {
return new Vector3d(x, y, z); return new Vector3i((int) x, (int) y, (int) z);
} }
public Location toLocation(World world) { public Location toLocation(World world) {
@@ -112,8 +116,27 @@ public class KLocation implements Cloneable {
return this; return this;
} }
public Vector getDirection() { public Vector3d getDirection() {
return MathUtils.getDirection(this); 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 @Override
@@ -1,5 +1,6 @@
package dev.brighten.ac.utils; package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.util.Vector3d;
import lombok.val; import lombok.val;
import me.hydro.emulator.util.mcp.MathHelper; import me.hydro.emulator.util.mcp.MathHelper;
import org.bukkit.Location; import org.bukkit.Location;
@@ -196,10 +197,6 @@ public class MathUtils {
return MathUtils.yawTo180D(playerRotation.getX() - expectedRotation.getX()); 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) { public static float distanceBetweenAngles(float a, float b) {
final float first = a % 360; final float first = a % 360;
final float second = b % 360; final float second = b % 360;
@@ -544,16 +541,14 @@ public class MathUtils {
return (short) num; return (short) num;
} }
/* Stolen from Bukkit */ public static Vector3d getDirection(KLocation loc) {
public static Vector getDirection(KLocation loc) { Vector3d vector = new Vector3d();
Vector vector = new Vector();
double rotX = loc.getYaw(); double rotX = loc.getYaw();
double rotY = loc.getPitch(); double rotY = loc.getPitch();
vector.setY(-Math.sin(Math.toRadians(rotY)));
double xz = Math.cos(Math.toRadians(rotY)); double xz = Math.cos(Math.toRadians(rotY));
vector.setX(-xz * Math.sin(Math.toRadians(rotX))); return new Vector3d(-xz * Math.sin(Math.toRadians(rotX)),
vector.setZ(xz * Math.cos(Math.toRadians(rotX))); -Math.sin(Math.toRadians(rotY)),
return vector; xz * Math.cos(Math.toRadians(rotX)));
} }
@@ -704,12 +699,12 @@ public class MathUtils {
return squareRoot; 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 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 f1 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI);
float f2 = -MathHelper.cos(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F); float f2 = -MathHelper.cos(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F);
float f3 = MathHelper.sin(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) { public static float sqrt(float number) {
+1 -1
Submodule Neo updated: b45b76d09d...feb79131a2
+4
View File
@@ -30,6 +30,10 @@
</build> </build>
<repositories> <repositories>
<repository>
<id>maven-central</id>
<url>https://nexus.funkemunky.cc/repository/maven-central/</url>
</repository>
<repository> <repository>
<id>spigot-repo</id> <id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>