diff --git a/Anticheat/pom.xml b/Anticheat/pom.xml index 67f0105..0971160 100644 --- a/Anticheat/pom.xml +++ b/Anticheat/pom.xml @@ -19,6 +19,10 @@ + + maven-central + https://nexus.funkemunky.cc/repository/maven-central/ + viaversion-repo https://repo.viaversion.com @@ -27,10 +31,6 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - evokegames - https://maven.evokegames.gg/snapshots - aikar https://repo.aikar.co/content/groups/aikar/ @@ -267,7 +267,7 @@ com.github.retrooper packetevents-spigot - 2.9.4 + 2.11.1 compile diff --git a/Anticheat/src/main/java/dev/brighten/ac/Anticheat.java b/Anticheat/src/main/java/dev/brighten/ac/Anticheat.java index 5c18a64..a5396ee 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/Anticheat.java +++ b/Anticheat/src/main/java/dev/brighten/ac/Anticheat.java @@ -17,6 +17,8 @@ import dev.brighten.ac.handler.PacketHandler; import dev.brighten.ac.handler.entity.FakeEntityTracker; import dev.brighten.ac.handler.keepalive.KeepaliveProcessor; import dev.brighten.ac.handler.keepalive.actions.ActionManager; +import dev.brighten.ac.handler.protocol.Protocol; +import dev.brighten.ac.handler.protocol.impl.NoAPI; import dev.brighten.ac.logging.LoggerManager; import dev.brighten.ac.utils.*; import dev.brighten.ac.utils.annotation.ConfigSetting; @@ -30,6 +32,7 @@ import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.WorldInfo; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.PackagePrivate; import org.bukkit.Bukkit; import org.bukkit.World; @@ -116,6 +119,9 @@ public class Anticheat extends JavaPlugin { private final RollingAverageDouble tps = new RollingAverageDouble(4, 20); private final Map worldInfoMap = new HashMap<>(); + @Setter + private Protocol protocol = new NoAPI(); + private final List commands = new ArrayList<>(); public static boolean allowDebug = true; @@ -252,7 +258,7 @@ public class Anticheat extends JavaPlugin { } catch (IllegalStateException e) { Anticheat.INSTANCE.getLogger().log(Level.SEVERE, "Check ID unregister failed", e); } - commandManager.getScheduler().cancelLocaleTask(); + commandPropertiesManager = null; try { diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/CheckData.java b/Anticheat/src/main/java/dev/brighten/ac/check/CheckData.java index 1255f4c..7ac1b5a 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/CheckData.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/CheckData.java @@ -23,5 +23,5 @@ public @interface CheckData { int punishVl() default 10; ClientVersion minVersion() default ClientVersion.V_1_8; - ClientVersion maxVersion() default ClientVersion.V_1_21_7; + ClientVersion maxVersion() default ClientVersion.V_1_21_11; } diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java index be1adc9..853d18a 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/Hitbox.java @@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import dev.brighten.ac.Anticheat; @@ -19,7 +20,6 @@ import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; -import org.bukkit.util.Vector; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; @@ -46,7 +46,7 @@ public class Hitbox extends Check { if(packet.getAction() != WrapperPlayClientInteractEntity.InteractAction.ATTACK) return; - Optional entity = player.getEntityLocationHandler().getTrackedEntity(packet.getEntityId()); + Optional entity = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(packet.getEntityId()); if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return; attacks.add(new Tuple<>(entity.get(), @@ -118,7 +118,7 @@ public class Hitbox extends Check { boolean didSneakOrElytra = player.getInfo().getLastSneak().isNotPassed(40) || player.getInfo().getLastElytra().isNotPassed(40); - List directions = new ArrayList<>(Arrays.asList(MathUtils.getDirection( + List directions = new ArrayList<>(Arrays.asList(MathUtils.getDirection( player.getMovement().getTo().getLoc().getYaw(), player.getMovement().getTo().getLoc().getPitch()), MathUtils.getDirection(player.getMovement().getFrom().getLoc().getYaw(), @@ -126,7 +126,7 @@ public class Hitbox extends Check { if(!didSneakOrElytra) { to.add(0, 1.62f, 0); - for (Vector direction : directions) { + for (Vector3d direction : directions) { for (SimpleCollisionBox targetBox : boxes) { final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox); @@ -143,7 +143,7 @@ public class Hitbox extends Check { } //Checking all possible eyeheights since client actions notoriously desync from the server side } else { - for (Vector direction : directions) { + for (Vector3d direction : directions) { for (double eyeHeight : player.getMovement().getEyeHeights()) { for (SimpleCollisionBox targetBox : boxes) { final AxisAlignedBB vanillaBox = new AxisAlignedBB(targetBox); @@ -180,7 +180,7 @@ public class Hitbox extends Check { debug("buffer: %.3f distance=%.2f hits=%s sneaking=%s", buffer, distance, hits, player.getInfo().isSneaking()); - } else if(player.getEntityLocationHandler().streak > 1) { + } else if(player.getEntityTrackHandler().streak > 1) { if (++hbuffer > 5) { flag("%.1f;%.1f;%.1f", entity.getNewEntityLocation().x, entity.getNewEntityLocation().y, entity.getNewEntityLocation().z); } diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java index 5c59229..2edfe84 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java @@ -1,6 +1,5 @@ package dev.brighten.ac.check.impl.combat.killaura; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientAnimation; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import dev.brighten.ac.api.check.CheckType; @@ -29,10 +28,10 @@ public class KABot extends Check { @Bind WAction packet = packet -> { - val optional = player.getEntityLocationHandler().getTrackedEntity(packet.getEntityId()); + val optional = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(packet.getEntityId()); if(optional.isPresent() - && (player.getEntityLocationHandler().clientHasEntity.get() + && (player.getEntityTrackHandler().clientHasEntity.get() || !optional.get().getFakeMobs().isEmpty())) { if(++buffer > 3) { flag("Attacked player without attacking bot!"); diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java index 23a4338..e243db5 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java @@ -1,6 +1,6 @@ package dev.brighten.ac.check.impl.combat.killaura; -import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.check.Check; @@ -13,7 +13,6 @@ import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.types.RayCollision; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; -import org.bukkit.util.Vector; /** * @author funkemunky @@ -43,14 +42,13 @@ public class KATrace extends Check { return; } - var trackedEntity = player.getEntityLocationHandler().getTrackedEntity(player.getInfo().getTarget().getEntityId()); + var trackedEntity = player.getWorldTracker().getCurrentWorld().get().getTrackedEntity(player.getInfo().getTarget().getEntityId()); if(trackedEntity.isEmpty()) { return; } // Getting the target's bounding box - SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget() - .getLocation(), trackedEntity.get()); + SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget().getLocation(), trackedEntity.get()); if(targetBox == null) return; @@ -59,12 +57,12 @@ public class KATrace extends Check { // Setting the player's eye height based on their sneak status origin.add(0, player.getEyeHeight(), 0); - final Vector originVec = origin.toVector(); + final Vector3d originVec = origin.toVector(); // Setting a trace based on their view direction RayCollision collision = new RayCollision(originVec, origin.getDirection()); - Vector targetPoint = collision.collisionPoint(targetBox); + Vector3d targetPoint = collision.collisionPoint(targetBox); //If the ray isn't collided, we might as well not run this check. Just a simple boxes on array check if(targetPoint == null) return; @@ -84,7 +82,7 @@ public class KATrace extends Check { continue; // We want to shrink the box slightly since there is a bit of a margin of error in the ray trace. - Vector point = collision.collisionPoint(box.copy().shrink(0.005f, 0.005f, 0.005f)); + Vector3d point = collision.collisionPoint(box.copy().shrink(0.005f, 0.005f, 0.005f)); if (point != null && originVec.distanceSquared(point) < dist - 0.2) { rayCollidedOnBlock = true; diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/calc/KACalc.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/calc/KACalc.java index c8905eb..27a9ca4 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/calc/KACalc.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/combat/killaura/calc/KACalc.java @@ -31,7 +31,7 @@ public class KACalc extends KListener { @Bind WAction flying = packet -> { if(player.getInfo().getTarget() == null || player.getInfo().lastAttack.isPassed(40)) return; - Optional optional = player.getEntityLocationHandler() + Optional optional = player.getWorldTracker().getCurrentWorld().get() .getTrackedEntity(player.getInfo().getTarget().getEntityId()); if(optional.isEmpty()) return; @@ -46,7 +46,7 @@ public class KACalc extends KListener { KLocation originKLoc = player.getMovement().getTo().getLoc().clone() .add(0, player.getInfo().isSneaking() ? 1.54f : 1.62f, 0); - double halfHeight = player.getInfo().getTarget().getEyeHeight() / 2; + double halfHeight = player.getInfo().getTarget().getPose().eyeHeight / 2; KLocation targetLocation = new KLocation(current.getX(), current.getY(), current.getZ()); var rotations = MathUtils .getRotation(originKLoc, targetLocation.clone().add(0, halfHeight, 0)); diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/Phase.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/Phase.java index 5de995c..bfbbd8e 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/Phase.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/Phase.java @@ -1,6 +1,7 @@ package dev.brighten.ac.check.impl.movement; import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag; +import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerPositionAndLook; import dev.brighten.ac.Anticheat; @@ -18,7 +19,6 @@ import dev.brighten.ac.utils.annotation.Bind; import dev.brighten.ac.utils.objects.evicting.EvictingSet; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import org.bukkit.Location; -import org.bukkit.util.Vector; import java.util.List; import java.util.Set; @@ -31,7 +31,7 @@ public class Phase extends Check { } private int ticks; - private final Set POSITIONS = new EvictingSet<>(10); + private final Set POSITIONS = new EvictingSet<>(10); private Location teleportLoc = null; @Bind diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/speed/Speed.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/speed/Speed.java index ed55820..bce7acc 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/speed/Speed.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/speed/Speed.java @@ -1,6 +1,7 @@ package dev.brighten.ac.check.impl.movement.speed; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.potion.PotionTypes; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.check.Check; @@ -36,11 +37,11 @@ public class Speed extends Check { moveFactor+= (float) (moveFactor * 0.30000001192092896D); - if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SPEED)) + if(player.getPotionHandler().hasPotionEffect(PotionTypes.SPEED)) moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SPEED) * (0.200000000298023224D)) * moveFactor); - if(player.getPotionHandler().hasPotionEffect(PotionEffectType.SLOW)) + if(player.getPotionHandler().hasPotionEffect(PotionTypes.SLOWNESS)) moveFactor += (float) ((PlayerUtils.getPotionEffectLevel(player.getBukkitPlayer(), PotionEffectType.SLOW) * (-0.15000000596046448D)) * moveFactor); diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java index 024ddeb..eb361a4 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/movement/velocity/VelocityB.java @@ -1,6 +1,8 @@ package dev.brighten.ac.check.impl.movement.velocity; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.potion.PotionTypes; +import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.check.Check; @@ -12,12 +14,10 @@ import dev.brighten.ac.utils.BlockUtils; import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.MathUtils; import dev.brighten.ac.utils.annotation.Bind; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import lombok.val; import me.hydro.emulator.util.mcp.MathHelper; -import org.bukkit.potion.PotionEffectType; import java.util.ArrayList; import java.util.List; @@ -61,8 +61,8 @@ public class VelocityB extends Check { val underBlockLoc = previousFrom != null ? player.getMovement().getFrom().getLoc() : player.getMovement().getTo().getLoc(); - WrappedBlock underMaterial = player.getBlockUpdateHandler() - .getBlock(new IntVector(MathHelper.floor_double(underBlockLoc.getX()), + WrappedBlock underMaterial = player.getWorldTracker() + .getBlock(new Vector3i(MathHelper.floor_double(underBlockLoc.getX()), MathHelper.floor_double(underBlockLoc.getY() - 1), MathHelper.floor_double(underBlockLoc.getZ()))); @@ -87,8 +87,8 @@ public class VelocityB extends Check { double pmotionx = 0, pmotionz = 0; boolean onGround = player.getMovement().getFrom().isOnGround(); - val speed = player.getPotionHandler().getEffectByType(PotionEffectType.SPEED); - val slow = player.getPotionHandler().getEffectByType(PotionEffectType.SLOW); + val speed = player.getPotionHandler().getEffectByType(PotionTypes.SPEED); + val slow = player.getPotionHandler().getEffectByType(PotionTypes.SLOWNESS); for (Iteration iteration : iterations) { float forward = iteration.f, strafe = iteration.s; @@ -138,9 +138,9 @@ public class VelocityB extends Check { aiMoveSpeed += aiMoveSpeed * 0.30000001192092896D; if (speed.isPresent()) - aiMoveSpeed += (speed.get().getAmplifier() + 1) * 0.20000000298023224D * aiMoveSpeed; + aiMoveSpeed += (speed.get().properties().amplifier() + 1) * 0.20000000298023224D * aiMoveSpeed; if (slow.isPresent()) - aiMoveSpeed += (slow.get().getAmplifier() + 1) * -0.15000000596046448D * aiMoveSpeed; + aiMoveSpeed += (slow.get().properties().amplifier() + 1) * -0.15000000596046448D * aiMoveSpeed; float f5; if (onGround) { diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java index 3c96f59..81d9279 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockA.java @@ -1,6 +1,7 @@ package dev.brighten.ac.check.impl.world; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import dev.brighten.ac.api.check.CheckType; @@ -35,7 +36,7 @@ public class BlockA extends Check { WAction blockPlace = packet -> { Vector3d loc = packet.getBlockPosition().toVector3d(); - WrappedBlock block = player.getBlockUpdateHandler().getBlock(loc); + WrappedBlock block = player.getWorldTracker().getBlock(new Vector3i(MathUtils.floor(loc.getX()), MathUtils.floor(loc.getY()), MathUtils.floor(loc.getZ()))); CollisionBox box = BlockData.getData(block.getType()).getBox(player, block, player.getPlayerVersion()); diff --git a/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockD.java b/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockD.java index 45682dc..12d0bd2 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockD.java +++ b/Anticheat/src/main/java/dev/brighten/ac/check/impl/world/BlockD.java @@ -14,12 +14,12 @@ import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.annotation.Bind; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.BlockData; -import java.util.*; +import java.util.HashMap; +import java.util.Map; @CheckData(name = "Block (D)", checkId = "blockc", type = CheckType.INTERACT) public class BlockD extends Check { @@ -45,7 +45,7 @@ public class BlockD extends Check { packet.getFace().getModY(), packet.getFace().getModZ()); - WrappedBlock block = new WrappedBlock(new IntVector(packet.getBlockPosition()), + WrappedBlock block = new WrappedBlock(packet.getBlockPosition(), placedType, WrappedBlockState.getDefaultState(placedType)); blockPlaceLocations.put(blockpos, block); diff --git a/Anticheat/src/main/java/dev/brighten/ac/data/APlayer.java b/Anticheat/src/main/java/dev/brighten/ac/data/APlayer.java index f000066..c06c092 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/data/APlayer.java +++ b/Anticheat/src/main/java/dev/brighten/ac/data/APlayer.java @@ -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.player.ClientVersion; 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.StateTypes; import com.github.retrooper.packetevents.util.Vector3d; 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.api.spigot.impl.LegacyPlayer; 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.obj.InstantAction; import dev.brighten.ac.data.obj.NormalAction; -import dev.brighten.ac.handler.EntityLocationHandler; +import dev.brighten.ac.handler.EntityTrackHandler; import dev.brighten.ac.handler.MovementHandler; import dev.brighten.ac.handler.PotionHandler; import dev.brighten.ac.handler.VelocityHandler; import dev.brighten.ac.handler.block.BlockUpdateHandler; +import dev.brighten.ac.handler.block.World; import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.handler.keepalive.KeepAlive; -import dev.brighten.ac.handler.protocol.Protocol; import dev.brighten.ac.messages.Messages; import dev.brighten.ac.packet.TransactionServerWrapper; -import dev.brighten.ac.utils.*; +import dev.brighten.ac.utils.Helper; +import dev.brighten.ac.utils.KLocation; +import dev.brighten.ac.utils.Tuple; +import dev.brighten.ac.utils.XMaterial; import dev.brighten.ac.utils.objects.evicting.EvictingList; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; @@ -49,7 +53,6 @@ import me.hydro.emulator.object.input.DataSupplier; import me.hydro.emulator.util.mcp.AxisAlignedBB; import me.hydro.emulator.util.mcp.BlockPos; import org.bukkit.entity.Player; -import org.bukkit.util.Vector; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; @@ -72,10 +75,10 @@ public class APlayer { private VelocityHandler velocityHandler; @Getter - private EntityLocationHandler entityLocationHandler; + private EntityTrackHandler entityTrackHandler; @Getter - private BlockUpdateHandler blockUpdateHandler; + private BlockUpdateHandler worldTracker; @Getter private CheckHandler checkHandler; @@ -138,87 +141,103 @@ public class APlayer { this.movement = new MovementHandler(this); this.potionHandler = new PotionHandler(this); this.velocityHandler = new VelocityHandler(this); - this.entityLocationHandler = new EntityLocationHandler(this); - this.blockUpdateHandler = new BlockUpdateHandler(this); + this.entityTrackHandler = new EntityTrackHandler(this); + this.worldTracker = new BlockUpdateHandler(this); this.checkHandler = new CheckHandler(this); this.info = new GeneralInformation(); this.lagInfo = new LagInformation(); this.blockInfo = new BlockInformation(this); + worldTracker.getCurrentWorld().set(new World(bukkitPlayer.getWorld().getName())); + creation.reset(); + playerVersion = ClientVersion.getById(Anticheat.INSTANCE.getProtocol().getPlayerVersion(this)); + Anticheat.INSTANCE.getScheduler().schedule(() -> { // Grabbing the protocol version of the player. Anticheat.INSTANCE.getLogger().info("Attempting Getting player version for " + getBukkitPlayer().getName()); - ClientVersion version = ClientVersion.getById(Protocol.getProtocol().getPlayerVersion(getBukkitPlayer())); + ClientVersion version = ClientVersion.getById(Anticheat.INSTANCE.getProtocol().getPlayerVersion(this)); this.playerVersion = version; 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 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 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 - 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); + + if(PacketEvents.getAPI().getServerManager().getVersion().isOlderThan(ServerVersion.V_1_9)) { + this.wrappedPlayer = new LegacyPlayer(getBukkitPlayer()); + } else this.wrappedPlayer = new ModernPlayer(getBukkitPlayer()); + + Cache> collisionCache = CacheBuilder.newBuilder() + .maximumSize(200) + .expireAfterWrite(100, TimeUnit.MILLISECONDS) + .build(); + + EMULATOR = new Emulator(new DataSupplier() { + @Override + public List 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 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 + 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() { @@ -228,7 +247,7 @@ public class APlayer { RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1)); - Vector loc1 = coll.collisionPoint(2); + Vector3d loc1 = coll.collisionPoint(2); List> dataList = new ArrayList<>(); @@ -330,10 +349,6 @@ public class APlayer { user.writePacketSilently(packet); } - public DimensionType getDimensionType() { - return user.getDimensionType(); - } - public void sendPacket(PacketWrapper packet) { user.sendPacket(packet); } diff --git a/Anticheat/src/main/java/dev/brighten/ac/data/info/BlockInformation.java b/Anticheat/src/main/java/dev/brighten/ac/data/info/BlockInformation.java index 1d13b31..0b89f6c 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/data/info/BlockInformation.java +++ b/Anticheat/src/main/java/dev/brighten/ac/data/info/BlockInformation.java @@ -4,6 +4,7 @@ import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; +import com.github.retrooper.packetevents.util.Vector3i; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.entity.TrackedEntity; @@ -132,11 +133,11 @@ public class BlockInformation { } final StateType type = - player.getBlockUpdateHandler().getBlock(new IntVector(x, y, z)).getType(); + player.getWorldTracker().getBlock(new Vector3i(x, y, z)).getType(); if (type != StateTypes.AIR) { - IntVector vec = new IntVector(x, y, z); + Vector3i vec = new Vector3i(x, y, z); CollisionBox blockBox = BlockData.getData(type) .getBox(player, vec, player.getPlayerVersion()); diff --git a/Anticheat/src/main/java/dev/brighten/ac/data/info/GeneralInformation.java b/Anticheat/src/main/java/dev/brighten/ac/data/info/GeneralInformation.java index 2bf3e45..a9d7301 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/data/info/GeneralInformation.java +++ b/Anticheat/src/main/java/dev/brighten/ac/data/info/GeneralInformation.java @@ -1,10 +1,12 @@ package dev.brighten.ac.data.info; import com.github.retrooper.packetevents.util.Vector3d; +import dev.brighten.ac.data.obj.Pose; import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.packet.PlayerCapabilities; import dev.brighten.ac.utils.KLocation; +import dev.brighten.ac.utils.KPotionEffect; import dev.brighten.ac.utils.PastLocation; import dev.brighten.ac.utils.math.RollingAverage; import dev.brighten.ac.utils.objects.evicting.EvictingList; @@ -12,8 +14,6 @@ import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import lombok.Getter; import lombok.Setter; -import org.bukkit.entity.LivingEntity; -import org.bukkit.potion.PotionEffect; import java.util.ArrayList; import java.util.Collections; @@ -33,8 +33,8 @@ public class GeneralInformation { lastBlockUpdate = new TickTimer(), lastMiscNear = new TickTimer(), lastHalfBlock = new TickTimer(), lastFence = new TickTimer(), lastFakeBotHit = new TickTimer(), lastInventoryOpen = new TickTimer(), botAttack = new TickTimer(), lastAttack = new TickTimer(), lastCanceledFlying = new TickTimer(); - public LivingEntity target; - public Optional groundJumpBoost; + public TrackedEntity target; + public Optional groundJumpBoost = Optional.empty(); public boolean serverGround, lastServerGround, canFly, nearGround, worldLoaded, generalCancel, inVehicle, creative, sneaking, lsneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity, breakingBlock, inventoryOpen, swimming; @@ -46,4 +46,7 @@ public class GeneralInformation { public List velocityHistory = Collections.synchronizedList(new EvictingList<>(5)); public List possibleCapabilities = new ArrayList<>(); private int clientGroundTicks, clientAirTicks; + private double walkSpeed, flySpeed; + private PlayerInput playerInput = PlayerInput.NONE; + private Pose pose; } diff --git a/Anticheat/src/main/java/dev/brighten/ac/data/info/PlayerInput.java b/Anticheat/src/main/java/dev/brighten/ac/data/info/PlayerInput.java new file mode 100644 index 0000000..b327498 --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/data/info/PlayerInput.java @@ -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); +} \ No newline at end of file diff --git a/Anticheat/src/main/java/dev/brighten/ac/data/obj/CMove.java b/Anticheat/src/main/java/dev/brighten/ac/data/obj/CMove.java index 086d881..257a429 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/data/obj/CMove.java +++ b/Anticheat/src/main/java/dev/brighten/ac/data/obj/CMove.java @@ -1,10 +1,10 @@ package dev.brighten.ac.data.obj; +import dev.brighten.ac.handler.block.World; import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import lombok.Getter; import lombok.Setter; -import org.bukkit.World; @Getter @Setter diff --git a/Anticheat/src/main/java/dev/brighten/ac/data/obj/Pose.java b/Anticheat/src/main/java/dev/brighten/ac/data/obj/Pose.java new file mode 100644 index 0000000..b7f7f1e --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/data/obj/Pose.java @@ -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; + } +} \ No newline at end of file diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/BBRevealHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/BBRevealHandler.java index a245681..c0ea050 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/BBRevealHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/BBRevealHandler.java @@ -1,13 +1,13 @@ package dev.brighten.ac.handler; import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes; +import com.github.retrooper.packetevents.util.Vector3i; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.utils.ItemBuilder; import dev.brighten.ac.utils.Materials; import dev.brighten.ac.utils.annotation.Init; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.world.BlockData; import dev.brighten.ac.utils.world.EntityData; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; @@ -31,7 +31,7 @@ import java.util.stream.Collectors; @Init public class BBRevealHandler implements Listener { - private final Map> blocksToShow = new HashMap<>(); + private final Map> blocksToShow = new HashMap<>(); private final Set entitiesToShow = new HashSet<>(); public static BBRevealHandler INSTANCE; @@ -52,9 +52,9 @@ public class BBRevealHandler implements Listener { if(player == null || !player.getWrappedPlayer().getItemInHand().isSimilar(wand)) return; if(event.getAction() == Action.RIGHT_CLICK_BLOCK) { - IntVector blockLoc = new IntVector(event.getClickedBlock().getX(), + Vector3i blockLoc = new Vector3i(event.getClickedBlock().getX(), event.getClickedBlock().getY(), event.getClickedBlock().getZ()); - Set blocksToShow = this.blocksToShow + Set blocksToShow = this.blocksToShow .computeIfAbsent(event.getPlayer().getUniqueId(), k -> new HashSet<>()); if(blocksToShow.contains(blockLoc)) { blocksToShow.remove(blockLoc); @@ -63,11 +63,11 @@ public class BBRevealHandler implements Listener { .create()); } else { blocksToShow.add(blockLoc); - WrappedBlock block = player.getBlockUpdateHandler().getBlock(blockLoc); + WrappedBlock block = player.getWorldTracker().getCurrentWorld().get().getBlock(blockLoc); event.getPlayer().spigot().sendMessage(new ComponentBuilder("Now showing block: ") .color(ChatColor.GREEN).color(ChatColor.WHITE).append(event.getClickedBlock().getType().name()) .color(ChatColor.GRAY) - .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)) .color(ChatColor.RED) .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; blocks.forEach(blockLoc -> { - var block = player.get().getBlockUpdateHandler().getBlock(blockLoc); + var block = player.get().getWorldTracker().getCurrentWorld().get().getBlock(blockLoc); var blockBox = BlockData.getData(block.getType()) .getBox(player.get(), blockLoc, player.get().getPlayerVersion()); diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/EntityTrackHandler.java similarity index 80% rename from Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java rename to Anticheat/src/main/java/dev/brighten/ac/handler/EntityTrackHandler.java index 8913e14..23bb39d 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/EntityTrackHandler.java @@ -1,14 +1,17 @@ package dev.brighten.ac.handler; +import com.github.retrooper.packetevents.protocol.attribute.Attribute; +import com.github.retrooper.packetevents.protocol.attribute.Attributes; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityPositionSync; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport; -import dev.brighten.ac.Anticheat; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.handler.entity.TrackedEntity; @@ -18,20 +21,15 @@ import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; import dev.brighten.ac.utils.world.types.RayCollision; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.bukkit.util.Vector; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @RequiredArgsConstructor -public class EntityLocationHandler { +public class EntityTrackHandler { private final APlayer data; - @Getter - private Map trackedEntities = new Int2ObjectArrayMap<>(); private final Timer lastFlying = new MillisTimer(); public Set canCreateMob = new HashSet<>(); @@ -43,7 +41,8 @@ public class EntityLocationHandler { EntityTypes.WITCH, EntityTypes.COW, EntityTypes.CREEPER); public Optional getTargetOfFakeMob(int fakeMobId) { - for (TrackedEntity value : trackedEntities.values()) { + for (TrackedEntity value : data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntities().values()) { if(value.getFakeMobs().stream().anyMatch(mob -> mob.getEntityId() == fakeMobId)) { return Optional.of(value.getEntityId()); } @@ -51,23 +50,6 @@ public class EntityLocationHandler { return Optional.empty(); } - public Optional getTrackedEntity(int entityId) { - TrackedEntity trackedEntity = trackedEntities.get(entityId); - - if(trackedEntity == null) { - var entity = Anticheat.INSTANCE.getWorldInfo(data.getBukkitPlayer().getWorld()).getEntity(entityId); - - if(entity.isEmpty()) { - return Optional.empty(); - } - KLocation loc = new KLocation(entity.get().getLocation()); - trackedEntity = new TrackedEntity(entityId, EntityTypes.PLAYER, loc); - trackedEntities.put(entityId, trackedEntity); - } - - return Optional.of(trackedEntity); - } - /** * * We are processing PacketPlayInFlying to iterate the tracked entity locations @@ -81,7 +63,7 @@ public class EntityLocationHandler { processZombie(); - trackedEntities.values().forEach(entity -> { + data.getWorldTracker().getCurrentWorld().get().getTrackedEntities().values().forEach(entity -> { var oldLoc = entity.getOldEntityLocation(); var newLoc = entity.getNewEntityLocation(); @@ -109,7 +91,8 @@ public class EntityLocationHandler { * @param packet WrappedOutRelativePosition */ void onRelPosition(WPacketPlayOutEntity packet) { - Optional entity = getTrackedEntity(packet.getId()); + Optional entity = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(packet.getId()); if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return; @@ -132,7 +115,8 @@ public class EntityLocationHandler { } void onPositionSync(WrapperPlayServerEntityPositionSync packet) { - Optional entity = getTrackedEntity(packet.getId()); + Optional entity = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(packet.getId()); if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return; @@ -161,7 +145,8 @@ public class EntityLocationHandler { * @param packet WrappedOutEntityTeleportPacket */ void onTeleportSent(WrapperPlayServerEntityTeleport packet) { - Optional entity = getTrackedEntity(packet.getEntityId()); + Optional entity = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(packet.getEntityId()); if(entity.isEmpty() || !allowedEntityTypes.contains(entity.get().getEntityType())) return; @@ -205,6 +190,28 @@ public class EntityLocationHandler { }); } + void updateAttributes(WrapperPlayServerUpdateAttributes attributes) { + data.runKeepaliveAction(ka -> { + TrackedEntity tracked = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(attributes.getEntityId()).orElse(null); + + if(tracked == null) return; + + for (WrapperPlayServerUpdateAttributes.Property property : attributes.getProperties()) { + Attribute attribute = property.getAttribute(); + + if(attributes.getEntityId() == data.getBukkitPlayer().getEntityId() && attribute == Attributes.MOVEMENT_SPEED) { + ValuedAttribute value = tracked.getAttribute(attribute); + + value.updateAttribute(property); + data.getInfo().setWalkSpeed(value.getValue()); + } + + tracked.updateAttribute(property); + } + }); + } + /** * * We are running an action when a transaction is received. If the Entity provided is currently a target, @@ -239,8 +246,10 @@ public class EntityLocationHandler { } public void removeFakeMob(int id) { - if(trackedEntities.containsKey(id)) { - List mobs = getTrackedEntity(id).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>()); + if(data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntities().containsKey(id)) { + List mobs = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(id).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>()); for (FakeMob mob : mobs) { mob.despawn(); @@ -256,9 +265,11 @@ public class EntityLocationHandler { private void createFakeMob(int entityId, KLocation location) { if (!canCreateMob.contains(entityId)) return; - Optional trackedEntity = getTrackedEntity(entityId); + Optional trackedEntity = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(entityId); - Optional playerEntity = getTrackedEntity(data.getBukkitPlayer().getEntityId()); + Optional playerEntity = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(data.getBukkitPlayer().getEntityId()); if(trackedEntity.isEmpty() || playerEntity.isEmpty()) return; @@ -281,7 +292,7 @@ public class EntityLocationHandler { RayCollision collision = new RayCollision(eyeLoc.toVector(), eyeLoc.getDirection()); - Vector point = collision.collisionPoint(0.4); + Vector3d point = collision.collisionPoint(0.4); FakeMob mob = new FakeMob(EntityTypes.SLIME); List> types = new ArrayList<>(); @@ -298,7 +309,8 @@ public class EntityLocationHandler { } public void processZombie() { - List fakeMobs = getTrackedEntity(data.getBukkitPlayer().getEntityId()) + List fakeMobs = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(data.getBukkitPlayer().getEntityId()) .map(TrackedEntity::getFakeMobs) .orElse(new ArrayList<>()); @@ -312,7 +324,7 @@ public class EntityLocationHandler { RayCollision collision = new RayCollision(eyeLoc.toVector(), eyeLoc.getDirection()); - Vector point = collision.collisionPoint(0.4); + Vector3d point = collision.collisionPoint(0.4); fakeMob.teleport(point.getX(), point.getY(), point.getZ(), 0 ,0); break; @@ -321,7 +333,8 @@ public class EntityLocationHandler { } public void processFakeMobs(int entityId, boolean rel, double x, double y, double z) { - List fakeMobs = getTrackedEntity(entityId).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>()); + List fakeMobs = data.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(entityId).map(TrackedEntity::getFakeMobs).orElse(new ArrayList<>()); if(fakeMobs.isEmpty()) { if(!rel) { diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/MovementHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/MovementHandler.java index 9354766..3f97eb2 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/MovementHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/MovementHandler.java @@ -3,6 +3,7 @@ package dev.brighten.ac.handler; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; import com.github.retrooper.packetevents.protocol.player.ClientVersion; +import com.github.retrooper.packetevents.protocol.potion.PotionTypes; import com.github.retrooper.packetevents.protocol.teleport.RelativeFlag; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; @@ -12,13 +13,13 @@ import dev.brighten.ac.compat.CompatHandler; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.obj.CMove; import dev.brighten.ac.utils.*; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.objects.evicting.EvictingList; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.TickTimer; import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.types.RayCollision; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; +import io.github.retrooper.packetevents.util.SpigotConversionUtil; import lombok.Getter; import lombok.Setter; import lombok.val; @@ -30,9 +31,6 @@ import me.hydro.emulator.util.Vector; import me.hydro.emulator.util.mcp.MathHelper; import me.hydro.emulator.util.mcp.MathHelper.FastMathType; import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.potion.PotionEffectType; import java.util.*; @@ -87,21 +85,14 @@ public class MovementHandler { private final Timer lastCinematic = new TickTimer(2); private final Timer lastReset = new TickTimer(2); private final EvictingList sensitivitySamples = new EvictingList<>(50); - private boolean modernMovement; + private final boolean modernMovement; + public MovementHandler(APlayer player) { this.player = player; - Player bplayer = player.getBukkitPlayer(); - // Initializing player location - to.setWorld(bplayer.getWorld()); - to.getLoc().setX(bplayer.getLocation().getX()); - to.getLoc().setY(bplayer.getLocation().getY()); - to.getLoc().setZ(bplayer.getLocation().getZ()); - to.getLoc().setYaw(bplayer.getLocation().getYaw()); - to.getLoc().setPitch(bplayer.getLocation().getPitch()); to.setBox(new SimpleCollisionBox(to.getLoc(), 0.6, 1.8)); - to.setOnGround(bplayer.isOnGround()); + to.setOnGround(false); // Setting from as same location as to from.setLoc(to); @@ -123,31 +114,32 @@ public class MovementHandler { */ final PotionEffect[] EFFECTS = new PotionEffect[3]; - for (org.bukkit.potion.PotionEffect potionEffect : player.getPotionHandler().potionEffects) { - if (potionEffect.getType().equals(PotionEffectType.SPEED)) { + for (KPotionEffect potionEffect : player.getPotionHandler().getPotionEffects()) { + if (potionEffect.potionType().equals(PotionTypes.SPEED)) { EFFECTS[0] = PotionEffect.builder() - .amplifier(potionEffect.getAmplifier()) + .amplifier(potionEffect.properties().amplifier()) .type(me.hydro.emulator.util.PotionEffectType.SPEED) .build(); - } else if (potionEffect.getType().equals(PotionEffectType.SLOW)) { + } else if (potionEffect.potionType().equals(PotionTypes.SLOWNESS)) { EFFECTS[1] = PotionEffect.builder() - .amplifier(potionEffect.getAmplifier()) + .amplifier(potionEffect.properties().amplifier()) .type(me.hydro.emulator.util.PotionEffectType.SLOW) .build(); - } else if (potionEffect.getType().equals(PotionEffectType.JUMP)) { + } else if (potionEffect.potionType().equals(PotionTypes.JUMP_BOOST)) { EFFECTS[2] = PotionEffect.builder() - .amplifier(potionEffect.getAmplifier()) + .amplifier(potionEffect.properties().amplifier()) .type(me.hydro.emulator.util.PotionEffectType.JUMP) .build(); } } - if(player.EMULATOR.getTags().contains("003") && !isZeroThree) { + if (player.EMULATOR.getTags().contains("003") && !isZeroThree) { runEmulation(to, true); } IterationResult minimum = null; - iteration: { + iteration: + { for (KLocation posLoc : new ArrayList<>(posLocs)) { // Resetting to prevent lag issues. @@ -157,7 +149,7 @@ public class MovementHandler { if (minimum == null || minimum.getOffset() > result.getOffset()) { minimum = result; - if(minimum.getOffset() < 1E-26) { + if (minimum.getOffset() < 1E-26) { // The player teleported, therefore we don't need to continue with predictions. break iteration; } @@ -171,96 +163,95 @@ public class MovementHandler { Motion previousMotion = player.EMULATOR.getMotion().clone(); - for (int forward : isZeroThree ? new int[] {0} : FULL_RANGE) { - for (int strafe : isZeroThree ? new int[] {0} : FULL_RANGE) { + for (int forward : isZeroThree ? new int[]{0} : FULL_RANGE) { + for (int strafe : isZeroThree ? new int[]{0} : FULL_RANGE) { for (boolean jumping : getJumpingIterations()) { for (boolean sprinting : getSprintingIterations(forward)) { - for (boolean usingItem : getUsingItemIterations(forward, strafe)) { - for (boolean hitSlow : getHitSlowIterations()) { - for (FastMathType fastMath : getFastMathIterations(forward, strafe)) { - for(Vector3d possibleVector : possibleVelocity) { - IterationInput input = IterationInput.builder() - .jumping(jumping) - .forward(forward) - .strafing(strafe) - .sprinting(sprinting) - .usingItem(usingItem) - .modernMovement(modernMovement) - .hitSlowdown(hitSlow) - .aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2) - .fastMathType(fastMath) - .sneaking(player.getInfo().isSneaking()) - .ground(from.isOnGround()) - .to(new Vector(to.getX(), to.getY(), to.getZ())) - .yaw(to.getYaw()) - .lastReportedBoundingBox(from.getBox().toNeo()) - .effectSpeed(EFFECTS[0]) - .effectSlow(EFFECTS[1]) - .waitingForTeleport(!posLocs.isEmpty()) - .effectJump(EFFECTS[2]).build(); + for (boolean usingItem : getUsingItemIterations(forward, strafe)) { + for (boolean hitSlow : getHitSlowIterations()) { + for (FastMathType fastMath : getFastMathIterations(forward, strafe)) { + for (Vector3d possibleVector : possibleVelocity) { + IterationInput input = IterationInput.builder() + .jumping(jumping) + .forward(forward) + .strafing(strafe) + .sprinting(sprinting) + .usingItem(usingItem) + .modernMovement(modernMovement) + .hitSlowdown(hitSlow) + .aiMoveSpeed(player.getBukkitPlayer().getWalkSpeed() / 2) + .fastMathType(fastMath) + .sneaking(player.getInfo().sneaking) + .ground(from.isOnGround()) + .to(new Vector(to.getX(), to.getY(), to.getZ())) + .yaw(to.getYaw()) + .lastReportedBoundingBox(from.getBox().toNeo()) + .effectSpeed(EFFECTS[0]) + .effectSlow(EFFECTS[1]) + .waitingForTeleport(!posLocs.isEmpty()) + .effectJump(EFFECTS[2]).build(); - boolean isVelocity = false; - if(possibleVector != null) { - // Setting the motion to the possible velocity vector. - player.EMULATOR.getMotion().setMotionX(possibleVector.getX()); - player.EMULATOR.getMotion().setMotionY(possibleVector.getY()); - player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ()); - // Has to be this way because order of operations in the emulator. - isVelocity = true; - } else { - // Resetting the motion to the previous motion. - player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX()); - player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY()); - player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ()); - } + boolean isVelocity = false; + if (possibleVector != null) { + // Setting the motion to the possible velocity vector. + player.EMULATOR.getMotion().setMotionX(possibleVector.getX()); + player.EMULATOR.getMotion().setMotionY(possibleVector.getY()); + player.EMULATOR.getMotion().setMotionZ(possibleVector.getZ()); + // Has to be this way because order of operations in the emulator. + isVelocity = true; + } else { + // Resetting the motion to the previous motion. + player.EMULATOR.getMotion().setMotionX(previousMotion.getMotionX()); + player.EMULATOR.getMotion().setMotionY(previousMotion.getMotionY()); + player.EMULATOR.getMotion().setMotionZ(previousMotion.getMotionZ()); + } - IterationResult result = player.EMULATOR.runIteration(input); + IterationResult result = player.EMULATOR.runIteration(input); - if(isVelocity) { - result.getTags().add("velocity"); - } + if (isVelocity) { + result.getTags().add("velocity"); + } - if(fastMath == FastMathType.FAST_LEGACY) { - result.getTags().add("fast_legacy"); - } else if(fastMath == FastMathType.VANILLA) { - result.getTags().add("vanilla"); - } else if(fastMath == FastMathType.FAST_NEW) { - result.getTags().add("fast_new"); - } else if(fastMath == FastMathType.MODERN_VANILLA) { - result.getTags().add("modern_vanilla"); - } + if (fastMath == FastMathType.FAST_LEGACY) { + result.getTags().add("fast_legacy"); + } else if (fastMath == FastMathType.VANILLA) { + result.getTags().add("vanilla"); + } else if (fastMath == FastMathType.FAST_NEW) { + result.getTags().add("fast_new"); + } else if (fastMath == FastMathType.MODERN_VANILLA) { + result.getTags().add("modern_vanilla"); + } - if(forward > 0) { - result.getTags().add("w-key"); - } else if(forward < 0) { - result.getTags().add("s-key"); - } + if (forward > 0) { + result.getTags().add("w-key"); + } else if (forward < 0) { + result.getTags().add("s-key"); + } - if(strafe > 0) { - result.getTags().add("d-key"); - } else if(strafe < 0) { - result.getTags().add("a-key"); - } + if (strafe > 0) { + result.getTags().add("d-key"); + } else if (strafe < 0) { + result.getTags().add("a-key"); + } - if (minimum == null || minimum.getOffset() > result.getOffset()) { - minimum = result; + if (minimum == null || minimum.getOffset() > result.getOffset()) { + minimum = result; - if (minimum.getOffset() < 1E-26) { - break iteration; + if (minimum.getOffset() < 1E-26) { + break iteration; + } } } } } - } } } } } } } - - if(minimum != null) { + if (minimum != null) { predicted = minimum.getPredicted(); double mx = player.EMULATOR.getMotion().getMotionX(); @@ -269,7 +260,7 @@ public class MovementHandler { double total = mx * mx + my * my + mz * mz; - if(total < 9E-4) { + if (total < 9E-4) { player.getInfo().lastCanceledFlying.reset(); minimum.getTags().add("003"); } @@ -282,11 +273,11 @@ public class MovementHandler { } player.EMULATOR.confirm(minimum.getIteration()); - if(minimum.getTags().contains("003")) { + if (minimum.getTags().contains("003")) { player.EMULATOR.getTags().add("003"); } - if(minimum.getTags().contains("bad_offset")) { + if (minimum.getTags().contains("bad_offset")) { player.EMULATOR.setLastReportedBoundingBox(getTo().getBox().toNeo()); } } @@ -294,7 +285,7 @@ public class MovementHandler { private FastMathType[] getFastMathIterations(int strafe, int forward) { // Because no movement is being applied, there is no angle calculation being done - if(strafe == 0 && forward == 0) { + if (strafe == 0 && forward == 0) { return new FastMathType[]{FastMathType.FAST_LEGACY}; } @@ -317,7 +308,9 @@ public class MovementHandler { private boolean[] getUsingItemIterations(int forward, int strafe) { return (forward == 0 && strafe == 0 || - !BlockUtils.isUsable(player.getBukkitPlayer().getItemInHand().getType())) ? ALWAYS_FALSE : IS_OR_NOT; + !BlockUtils.isUsable(player.getPlayerVersion(), + SpigotConversionUtil.fromBukkitItemMaterial(player.getBukkitPlayer().getInventory().getItemInHand().getType()))) + ? ALWAYS_FALSE : IS_OR_NOT; } private boolean[] getJumpingIterations() { @@ -336,13 +329,13 @@ public class MovementHandler { && player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17); checkMovement = teleportsToConfirm == 0 && posLocs.isEmpty(); - + if (checkMovement) { moveTicks++; if (!packet.hasPositionChanged()) moveTicks = 1; } else moveTicks = 0; - if(excuseNextFlying) { + if (excuseNextFlying) { return; } @@ -359,10 +352,10 @@ public class MovementHandler { if (moveTicks > 0) { // Updating block locations - player.getInfo().setBlockOnTo(Optional.of(player.getBlockUpdateHandler() - .getBlock(new IntVector(to.getLoc())))); - player.getInfo().setBlockBelow(Optional.of(player.getBlockUpdateHandler() - .getBlock(new IntVector(to.getLoc().clone().subtract(0, 1, 0))))); + player.getInfo().setBlockOnTo(Optional.of(player.getWorldTracker() + .getBlock(to.getLoc().toVector3i()))); + player.getInfo().setBlockBelow(Optional.of(player.getWorldTracker() + .getBlock(to.getLoc().clone().subtract(0, 1, 0).clone().toVector3i()))); if (packet.hasPositionChanged()) { // Updating player bounding box @@ -486,7 +479,7 @@ public class MovementHandler { player.getInfo().setWasOnSlime(player.getBlockInfo().onSlime); groundTicks++; airTicks = 0; - player.getInfo().groundJumpBoost = player.getPotionHandler().getEffectByType(PotionEffectType.JUMP); + player.getInfo().groundJumpBoost = player.getPotionHandler().getEffectByType(PotionTypes.JUMP_BOOST); } else { player.getInfo().groundJumpBoost = Optional.empty(); airTicks++; @@ -503,7 +496,7 @@ public class MovementHandler { .anyMatch(capability -> capability.canFly)); boolean hasLevitation = PacketEvents.getAPI().getServerManager().getVersion().isNewerThanOrEquals(ServerVersion.V_1_9) - && player.getPotionHandler().hasPotionEffect(XPotion.LEVITATION.getPotionEffectType()); + && player.getPotionHandler().hasPotionEffect(PotionTypes.LEVITATION); player.getInfo().setRiptiding(CompatHandler.getINSTANCE().isRiptiding(player.getBukkitPlayer())); player.getInfo().setGliding(CompatHandler.getINSTANCE().isGliding(player.getBukkitPlayer())); @@ -570,7 +563,7 @@ it // generate a method that processes velocityHistory and compares to current deltaY. private void processVelocity() { //Iterate through player.getInfo().getVelocityHistory() and compare to current deltaY. - if(player.getInfo().isDoingVelocity()) { + if (player.getInfo().isDoingVelocity()) { player.getInfo().getVelocity().reset(); } synchronized (player.getInfo().getVelocityHistory()) { @@ -590,22 +583,22 @@ it } private void processBotMove(WrapperPlayClientPlayerFlying packet) { - if(player.getMob() == null) return; + if (player.getMob() == null) return; if (packet.hasPositionChanged() || packet.hasRotationChanged()) { KLocation origin = to.getLoc().clone().add(0, 1.7, 0); final double MULTIPLIER = Math.max(-0.5, Math.min(-1, -1 / (Math.abs(deltaYaw) * 0.25))); RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection() - .multiply(MULTIPLIER).setY(0)); + .multiply(MULTIPLIER).withY(0)); - Location loc1 = coll.collisionPoint(1.5).toLocation(player.getBukkitPlayer().getWorld()); + KLocation loc1 = new KLocation(coll.collisionPoint(1.5)); if (player.getInfo().botAttack.isNotPassed(7)) { loc1.setY(Math.max(origin.getY() + 2, loc1.getY())); player.getMob().teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch()); } else { loc1.setY(Math.max(origin.getY() + 0.6, loc1.getY())); - if(Math.random() > 0.2) + if (Math.random() > 0.2) Anticheat.INSTANCE.getRunUtils().taskLaterAsync(() -> player.getMob() .teleport(loc1.getX(), loc1.getY(), loc1.getZ(), loc1.getYaw(), loc1.getPitch()), 5); } @@ -661,7 +654,7 @@ it public void runPositionHackFix() { if (sentPositionUpdate) return; - player.sendPacket(new WrapperPlayServerPlayerPositionAndLook(0, Vector3d.zero(), new Vector3d(0,0,0), 0, 0, + player.sendPacket(new WrapperPlayServerPlayerPositionAndLook(0, Vector3d.zero(), new Vector3d(0, 0, 0), 0, 0, relFlags)); player.getBukkitPlayer().sendMessage("§c[Anticheat] §7Position update sent to fix movement issues."); @@ -725,10 +718,10 @@ it packet.getYaw(), packet.getPitch()); if (packet.getRelativeFlags().has(RelativeFlag.X)) { - loc.add(player.getMovement().getTo().getLoc().getX(), 0 ,0); + loc.add(player.getMovement().getTo().getLoc().getX(), 0, 0); } if (packet.getRelativeFlags().has(RelativeFlag.Y)) { - loc.add(0, player.getMovement().getTo().getLoc().getY() ,0); + loc.add(0, player.getMovement().getTo().getLoc().getY(), 0); } if (packet.getRelativeFlags().has(RelativeFlag.Z)) { loc.add(0, 0, player.getMovement().getTo().getLoc().getZ()); @@ -743,7 +736,6 @@ it teleportsToConfirm++; loc.setTimeStamp(System.currentTimeMillis()); - player.runKeepaliveAction(ka -> { teleportsToConfirm--; @@ -762,7 +754,7 @@ it * * @param location Location */ - public void moveTo(Location location) { + public void moveTo(KLocation location) { KLocation newLoc = new KLocation(location); to.getLoc().setLocation(newLoc); to.getLoc().setLocation(newLoc); @@ -814,7 +806,7 @@ it * @param packet WrapperPlayClientPlayerFlyingh */ private void setTo(WrapperPlayClientPlayerFlying packet) { - to.setWorld(player.getBukkitPlayer().getWorld()); + to.setWorld(player.getWorldTracker().getCurrentWorld().get()); if (packet.hasPositionChanged()) { to.getLoc().setX(packet.getLocation().getX()); to.getLoc().setY(packet.getLocation().getY()); diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/PacketHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/PacketHandler.java index 557d1f5..2f7d9d5 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/PacketHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/PacketHandler.java @@ -18,6 +18,8 @@ import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteStreams; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.data.info.PlayerInput; +import dev.brighten.ac.data.obj.Pose; import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.packet.PlayerCapabilities; @@ -26,10 +28,7 @@ import dev.brighten.ac.packet.WPacketPlayOutEntity; import dev.brighten.ac.utils.BlockUtils; import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.MovementUtils; -import io.github.retrooper.packetevents.util.SpigotConversionUtil; import lombok.val; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; import java.util.Optional; @@ -38,13 +37,14 @@ public class PacketHandler { public boolean processReceive(APlayer player, PacketReceiveEvent event) { long timestamp = System.currentTimeMillis(); Object wrapped; - if (event.getPacketType().equals(PacketType.Play.Client.PONG) - || event.getPacketType().equals(PacketType.Play.Client.WINDOW_CONFIRMATION)) { + + boolean cancel = false; + if (event.getPacketType().equals(PacketType.Play.Client.PONG) || event.getPacketType().equals(PacketType.Play.Client.WINDOW_CONFIRMATION)) { TransactionClientWrapper packet = new TransactionClientWrapper(event); wrapped = packet; - if(packet.getId() == 0) { + if (packet.getId() == 0) { if (Anticheat.INSTANCE.getKeepaliveProcessor().keepAlives.get(packet.getAction()) != null) { Anticheat.INSTANCE.getKeepaliveProcessor().addResponse(player, packet.getAction()); @@ -68,7 +68,7 @@ public class PacketHandler { synchronized (player.instantTransaction) { var iterator = player.instantTransaction.keySet().iterator(); - while(iterator.hasNext()) { + while (iterator.hasNext()) { Short key = iterator.next(); if (key > ka.id) { @@ -96,7 +96,7 @@ public class PacketHandler { synchronized (player.keepAliveLock) { player.keepAliveStamps.removeIf(action -> { - if(action.stamp > ka.id) { + if (action.stamp > ka.id) { return false; } @@ -110,10 +110,17 @@ public class PacketHandler { Optional.ofNullable(player.instantTransaction.remove(packet.getAction())) .ifPresent(t -> t.two.accept(t.one)); } - } else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) - || event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION) - || event.getPacketType().equals(PacketType.Play.Client.PLAYER_ROTATION) - || event.getPacketType().equals(PacketType.Play.Client.PLAYER_FLYING)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_INPUT)) { + WrapperPlayClientPlayerInput packet = new WrapperPlayClientPlayerInput(event); + + wrapped = packet; + + player.getInfo().setSprinting(packet.isSprint()); + player.getInfo().setSneaking(packet.isShift()); + player.getInfo().setPlayerInput(PlayerInput.getFromPacket(packet)); + + player.getBukkitPlayer().sendMessage("packet: " + packet.isForward()); + } else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION) || event.getPacketType().equals(PacketType.Play.Client.PLAYER_POSITION) || event.getPacketType().equals(PacketType.Play.Client.PLAYER_ROTATION) || event.getPacketType().equals(PacketType.Play.Client.PLAYER_FLYING)) { WrapperPlayClientPlayerFlying packet = new WrapperPlayClientPlayerFlying(event); wrapped = packet; if (player.getMovement().isExcuseNextFlying()) { @@ -127,7 +134,7 @@ public class PacketHandler { player.getLagInfo().setLastFlying(timestamp); - player.getEntityLocationHandler().onFlying(); + player.getEntityTrackHandler().onFlying(); if (player.getPlayerVersion().isNewerThanOrEquals(ClientVersion.V_1_17) && packet.hasPositionChanged() && packet.hasRotationChanged() @@ -145,17 +152,17 @@ public class PacketHandler { player.getVelocityHandler().onFlyingPost(packet); return result; - } else if(event.getPacketType().equals(PacketType.Play.Client.STEER_VEHICLE)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.STEER_VEHICLE)) { WrapperPlayClientSteerVehicle packet = new WrapperPlayClientSteerVehicle(event); wrapped = packet; // Check for isUnmount() - if (player.getBukkitPlayer().isInsideVehicle() && packet.isUnmount()) { + if (player.getInfo().isInVehicle() && packet.isUnmount()) { player.getInfo().getVehicleSwitch().reset(); player.getInfo().setInVehicle(false); } - } else if(event.getPacketType().equals(PacketType.Play.Client.ENTITY_ACTION)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.ENTITY_ACTION)) { WrapperPlayClientEntityAction packet = new WrapperPlayClientEntityAction(event); wrapped = packet; @@ -178,13 +185,13 @@ public class PacketHandler { break; } case START_FLYING_WITH_ELYTRA: { - if(player.isGlidePossible()) { + if (player.isGlidePossible()) { player.getInfo().setGliding(true); } break; } } - } else if(event.getPacketType().equals(PacketType.Play.Client.INTERACT_ENTITY)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.INTERACT_ENTITY)) { WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event); wrapped = packet; @@ -192,39 +199,44 @@ public class PacketHandler { FakeMob mob = Anticheat.INSTANCE.getFakeTracker().getEntityById(packet.getEntityId()); if (packet.getAction() == WrapperPlayClientInteractEntity.InteractAction.ATTACK) { + if (player.hitsToCancel > 0) { + player.hitsToCancel--; + cancel = true; + } if (mob != null) { - player.getEntityLocationHandler().getTargetOfFakeMob(mob.getEntityId()) + player.getEntityTrackHandler().getTargetOfFakeMob(mob.getEntityId()) .ifPresent(targetId -> { - player.getEntityLocationHandler().removeFakeMob(targetId); + player.getEntityTrackHandler().removeFakeMob(targetId); player.getInfo().lastFakeBotHit.reset(); }); if (player.getMob().getEntityId() == packet.getEntityId()) { player.getInfo().botAttack.reset(); } } else { - Optional target = Anticheat.INSTANCE.getWorldInfo(player.getBukkitPlayer().getWorld()).getEntity(packet.getEntityId()); + Optional target = player.getWorldTracker().getCurrentWorld().get() + .getTrackedEntity(packet.getEntityId()); - if(target.isPresent() && target.get() instanceof LivingEntity entity) { + if (target.isPresent() && target.get().getEntityType().isInstanceOf(EntityTypes.LIVINGENTITY)) { if (player.getInfo().lastFakeBotHit.isPassed(400) && Math.random() > 0.9) { - player.getEntityLocationHandler().canCreateMob.add(entity.getEntityId()); + player.getEntityTrackHandler().canCreateMob.add(target.get().getEntityId()); } - player.getInfo().setTarget(entity); + player.getInfo().setTarget(target.get()); } } player.getInfo().lastAttack.reset(); } - } else if(event.getPacketType().equals(PacketType.Play.Client.ANIMATION)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.ANIMATION)) { WrapperPlayClientAnimation packet = new WrapperPlayClientAnimation(event); wrapped = packet; - if(packet.getHand() == InteractionHand.MAIN_HAND) { + if (packet.getHand() == InteractionHand.MAIN_HAND) { long delta = timestamp - player.getInfo().lastArmSwing; player.getInfo().cps.add(1000D / delta, timestamp); player.getInfo().lastArmSwing = timestamp; } - } else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_BLOCK_PLACEMENT)) { WrapperPlayClientPlayerBlockPlacement packet = new WrapperPlayClientPlayerBlockPlacement(event); wrapped = packet; @@ -236,19 +248,19 @@ public class PacketHandler { // Used item if (pos.getX() == -1 && (pos.getY() == 255 | pos.getY() == -1) && pos.getZ() == -1 && stack.isPresent() - && BlockUtils.isUsable(SpigotConversionUtil.toBukkitItemMaterial(stack.get().getType()))) { + && BlockUtils.isUsable(player.getPlayerVersion(), stack.get().getType())) { player.getInfo().getLastUseItem().reset(); } - player.getBlockUpdateHandler().onPlace(packet); - } else if(event.getPacketType().equals(PacketType.Play.Client.PLAYER_DIGGING)) { + player.getWorldTracker().onPlace(packet); + } else if (event.getPacketType().equals(PacketType.Play.Client.PLAYER_DIGGING)) { WrapperPlayClientPlayerDigging packet = new WrapperPlayClientPlayerDigging(event); wrapped = packet; player.getInfo().getLastBlockDig().reset(); - player.getBlockUpdateHandler().onDig(packet); - } else if(event.getPacketType().equals(PacketType.Play.Client.CLIENT_STATUS)) { + player.getWorldTracker().onDig(packet); + } else if (event.getPacketType().equals(PacketType.Play.Client.CLIENT_STATUS)) { WrapperPlayClientClientStatus packet = new WrapperPlayClientClientStatus(event); wrapped = packet; @@ -258,10 +270,10 @@ public class PacketHandler { player.getInfo().lastInventoryOpen.reset(); return false; } - } else if(event.getPacketType().equals(PacketType.Play.Client.CLOSE_WINDOW)) { + } else if (event.getPacketType().equals(PacketType.Play.Client.CLOSE_WINDOW)) { wrapped = new WrapperPlayClientCloseWindow(event); player.getInfo().setInventoryOpen(false); - } else if(event.getPacketType() == PacketType.Play.Client.PLUGIN_MESSAGE) { + } else if (event.getPacketType().equals(PacketType.Play.Client.PLUGIN_MESSAGE)) { WrapperPlayClientPluginMessage packet = new WrapperPlayClientPluginMessage(event); wrapped = packet; @@ -286,7 +298,7 @@ public class PacketHandler { + ": " + wrapped); } - return player.getCheckHandler().callSyncPacket(wrapped, timestamp); + return cancel || player.getCheckHandler().callSyncPacket(wrapped, timestamp); } public boolean processSend(APlayer player, PacketSendEvent event) { @@ -309,30 +321,36 @@ public class PacketHandler { player.getInfo().getPossibleCapabilities().clear(); } }, true); + } else if(event.getPacketType() == PacketType.Play.Server.UPDATE_ATTRIBUTES) { + WrapperPlayServerUpdateAttributes packet = new WrapperPlayServerUpdateAttributes(event); + + wrapped = packet; + + player.getEntityTrackHandler().updateAttributes(packet); } else if(event.getPacketType() == PacketType.Play.Server.BLOCK_CHANGE) { WrapperPlayServerBlockChange packet = new WrapperPlayServerBlockChange(event); wrapped = packet; - player.getBlockUpdateHandler().runUpdate(packet); + player.getWorldTracker().runUpdate(packet); } else if(event.getPacketType() == PacketType.Play.Server.MULTI_BLOCK_CHANGE) { WrapperPlayServerMultiBlockChange packet = new WrapperPlayServerMultiBlockChange(event); wrapped = packet; - player.getBlockUpdateHandler().runUpdate(packet); + player.getWorldTracker().runUpdate(packet); } else if(event.getPacketType() == PacketType.Play.Server.CHUNK_DATA) { WrapperPlayServerChunkData packet = new WrapperPlayServerChunkData(event); wrapped = packet; - player.getBlockUpdateHandler().runUpdate(packet); + player.getWorldTracker().runUpdate(packet); } else if(event.getPacketType() == PacketType.Play.Server.MAP_CHUNK_BULK) { WrapperPlayServerChunkDataBulk packet = new WrapperPlayServerChunkDataBulk(event); wrapped = packet; - player.getBlockUpdateHandler().runUpdate(packet); + player.getWorldTracker().runUpdate(packet); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_EFFECT) { WrapperPlayServerEntityEffect packet = new WrapperPlayServerEntityEffect(event); @@ -394,18 +412,19 @@ public class PacketHandler { } else if(event.getPacketType() == PacketType.Play.Server.RESPAWN) { wrapped = new WrapperPlayServerRespawn(event); if(player.getPlayerVersion().isOlderThan(ClientVersion.V_1_14)) { - player.runKeepaliveAction(k -> player.getBukkitPlayer().setSprinting(false), 1); + player.runKeepaliveAction(k -> player.getInfo().setSprinting(false), 1); } - player.runKeepaliveAction(ka -> player.getInfo().lastRespawn.reset()); - player.runKeepaliveAction(ka -> player.getBlockUpdateHandler() - .setMinHeight(player.getDimensionType())); + player.runKeepaliveAction(ka -> { + player.getInfo().lastRespawn.reset(); + player.getInfo().setPose(Pose.STANDING); + }); + player.runKeepaliveAction(ka -> player.getWorldTracker() + .onRespawn((WrapperPlayServerRespawn) wrapped)); } else if(event.getPacketType() == PacketType.Play.Server.PLAYER_POSITION_AND_LOOK) { WrapperPlayServerPlayerPositionAndLook packet = new WrapperPlayServerPlayerPositionAndLook(event); wrapped = packet; - player.runKeepaliveAction(ka -> - player.getBlockUpdateHandler().setMinHeight(player.getDimensionType())); player.getMovement().addPosition(packet); } else if(event.getPacketType() == PacketType.Play.Server.ATTACH_ENTITY) { WrapperPlayServerAttachEntity packet = new WrapperPlayServerAttachEntity(event); @@ -423,37 +442,37 @@ public class PacketHandler { wrapped = packet; - player.getEntityLocationHandler().onEntityDestroy(packet); + player.getEntityTrackHandler().onEntityDestroy(packet); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_TELEPORT) { WrapperPlayServerEntityTeleport packet = new WrapperPlayServerEntityTeleport(event); wrapped = packet; - player.getEntityLocationHandler().onTeleportSent(packet); + player.getEntityTrackHandler().onTeleportSent(packet); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_MOVEMENT) { WrapperPlayServerEntityMovement packet = new WrapperPlayServerEntityMovement(event); wrapped = packet; - player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); + player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet)); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE) { WrapperPlayServerEntityRelativeMove packet = new WrapperPlayServerEntityRelativeMove(event); wrapped = packet; - player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); + player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet)); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_ROTATION) { WrapperPlayServerEntityRotation packet = new WrapperPlayServerEntityRotation(event); wrapped = packet; - player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); + player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet)); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_RELATIVE_MOVE_AND_ROTATION) { WrapperPlayServerEntityRelativeMoveAndRotation packet = new WrapperPlayServerEntityRelativeMoveAndRotation(event); wrapped = packet; - player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); + player.getEntityTrackHandler().onRelPosition(new WPacketPlayOutEntity(packet)); } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) { WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event); wrapped = packet; @@ -462,7 +481,7 @@ public class PacketHandler { double y = packet.getPosition().getY(); double z = packet.getPosition().getZ(); - player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(), + player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(), new TrackedEntity(packet.getEntityId(), packet.getEntityType(), new KLocation(x, y, z, packet.getYaw(), packet.getPitch()))); } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_LIVING_ENTITY) { @@ -474,7 +493,7 @@ public class PacketHandler { double y = packet.getPosition().getY(); double z = packet.getPosition().getZ(); - player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(), + player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(), new TrackedEntity(packet.getEntityId(), packet.getEntityType(), new KLocation(x, y, z, packet.getYaw(), packet.getPitch()))); } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PLAYER) { @@ -487,7 +506,7 @@ public class PacketHandler { double z = packet.getPosition().getZ(); - player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(), + player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(), new TrackedEntity(packet.getEntityId(), EntityTypes.PLAYER, new KLocation(x, y, z, packet.getYaw(),packet.getPitch()))); } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_PAINTING) { @@ -499,14 +518,14 @@ public class PacketHandler { int y = packet.getPosition().getY(); int z = packet.getPosition().getZ(); - player.getEntityLocationHandler().getTrackedEntities().put(packet.getEntityId(), + player.getWorldTracker().getCurrentWorld().get().getTrackedEntities().put(packet.getEntityId(), new TrackedEntity(packet.getEntityId(), EntityTypes.PAINTING, new KLocation(x, y, z))); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_POSITION_SYNC) { WrapperPlayServerEntityPositionSync packet = new WrapperPlayServerEntityPositionSync(event); wrapped = packet; - player.getEntityLocationHandler().onPositionSync(packet); + player.getEntityTrackHandler().onPositionSync(packet); } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) { wrapped = new WrapperPlayServerEntityMetadata(event); }else if(event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) { @@ -514,7 +533,7 @@ public class PacketHandler { wrapped = packet; - player.getEntityLocationHandler().onEntityDestroy(packet); + player.getEntityTrackHandler().onEntityDestroy(packet); } else if(event.getPacketType() == PacketType.Play.Server.CLOSE_WINDOW) { wrapped = new WrapperPlayServerCloseWindow(event); player.runKeepaliveAction(ka -> player.getInfo().setInventoryOpen(false)); diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/PotionHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/PotionHandler.java index 4678cbb..8ff43e3 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/PotionHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/PotionHandler.java @@ -1,59 +1,118 @@ package dev.brighten.ac.handler; +import com.github.retrooper.packetevents.protocol.potion.PotionType; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.utils.KPotionEffect; +import dev.brighten.ac.utils.KProperties; import io.github.retrooper.packetevents.util.SpigotConversionUtil; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; +import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class PotionHandler { private final APlayer data; - public List potionEffects = new CopyOnWriteArrayList<>(); + private final List potionEffects = new ArrayList<>(); + private final ReadWriteLock lock = new ReentrantReadWriteLock(); - public PotionHandler(APlayer data) { + public PotionHandler(APlayer data) { this.data = data; - potionEffects.addAll(data.getBukkitPlayer().getActivePotionEffects()); + lock.writeLock().lock(); + + try { + data.getBukkitPlayer().getActivePotionEffects().stream() + .map(pe -> + new KPotionEffect( + SpigotConversionUtil.fromBukkitPotionEffectType(pe.getType()), + KProperties.fromBukkit(pe) + )) + .forEach(potionEffects::add); + } finally { + lock.writeLock().unlock(); + } } public void onFlying(WrapperPlayClientPlayerFlying packet) { - for (PotionEffect effect : potionEffects) { - if(data.getBukkitPlayer().hasPotionEffect(effect.getType())) continue; + lock.readLock().lock(); + try { + for (KPotionEffect effect : potionEffects) { + lock.readLock().lock(); - data.runKeepaliveAction(d -> data.getPotionHandler().potionEffects.remove(effect)); + try { + if (data.getBukkitPlayer().hasPotionEffect(SpigotConversionUtil.toBukkitPotionEffectType(effect.potionType()))) continue; + + data.runKeepaliveAction(d -> { + lock.writeLock().lock(); + try { + data.getPotionHandler().potionEffects.remove(effect); + } finally { + lock.writeLock().unlock(); + } + }); + } finally { + lock.readLock().unlock(); + } + } + } finally { + lock.readLock().unlock(); } } public void onPotionEffect(WrapperPlayServerEntityEffect packet) { data.runKeepaliveAction(d -> { - var type = SpigotConversionUtil.toBukkitPotionEffectType(packet.getPotionType()); - data.getPotionHandler().potionEffects.stream().filter(pe -> pe.getType().equals(type)) - .forEach(data.getPotionHandler().potionEffects::remove); - data.getPotionHandler().potionEffects - .add(new PotionEffect(type, packet.getEffectDurationTicks(), packet.getEffectAmplifier(), - packet.isAmbient())); + var type = packet.getPotionType(); + lock.writeLock().lock(); + try { + data.getPotionHandler().potionEffects.removeIf(pe -> pe.potionType().equals(type)); + data.getPotionHandler().potionEffects + .add(new KPotionEffect(type, new KProperties(packet.getEffectAmplifier() + , packet.getEffectDurationTicks(), + packet.isAmbient(), packet.isVisible(), packet.isShowIcon(), null))); + } finally { + lock.readLock().unlock(); + } }); } - public boolean hasPotionEffect(PotionEffectType type) { - for (PotionEffect potionEffect : potionEffects) { - if(potionEffect.getType().equals(type)) - return true; + public boolean hasPotionEffect(PotionType type) { + lock.readLock().lock(); + try { + for (KPotionEffect potionEffect : potionEffects) { + if (potionEffect.potionType().equals(type)) + return true; + } + return false; + } finally { + lock.readLock().unlock(); } - return false; } - public Optional getEffectByType(PotionEffectType type) { - for (PotionEffect potionEffect : potionEffects) { - if(potionEffect.getType().equals(type)) - return Optional.of(potionEffect); + public Optional getEffectByType(PotionType type) { + lock.readLock().lock(); + try { + for (KPotionEffect potionEffect : potionEffects) { + if (potionEffect.potionType().equals(type)) + return Optional.of(potionEffect); + } + return Optional.empty(); + } finally { + lock.readLock().unlock(); } - return Optional.empty(); } -} + + public List getPotionEffects() { + lock.readLock().lock(); + + try { + return new ArrayList<>(potionEffects); + } finally { + lock.readLock().unlock(); + } + } +} \ No newline at end of file diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/ValuedAttribute.java b/Anticheat/src/main/java/dev/brighten/ac/handler/ValuedAttribute.java new file mode 100644 index 0000000..7ca1bba --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/ValuedAttribute.java @@ -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); + } +} diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java index 256731c..6bb30e8 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java @@ -1,67 +1,68 @@ package dev.brighten.ac.handler.block; import com.github.retrooper.packetevents.PacketEvents; -import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; import com.github.retrooper.packetevents.protocol.player.DiggingAction; +import com.github.retrooper.packetevents.protocol.world.BlockFace; import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk; import com.github.retrooper.packetevents.protocol.world.chunk.Column; import com.github.retrooper.packetevents.protocol.world.chunk.TileEntity; -import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_16.Chunk_v1_9; -import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_7.Chunk_v1_7; -import com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_8.Chunk_v1_8; -import com.github.retrooper.packetevents.protocol.world.chunk.impl.v_1_18.Chunk_v1_18; -import com.github.retrooper.packetevents.protocol.world.chunk.palette.PaletteType; -import com.github.retrooper.packetevents.protocol.world.dimension.DimensionType; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; -import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBlockChange; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChunkData; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerChunkDataBulk; -import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerMultiBlockChange; -import dev.brighten.ac.Anticheat; +import com.github.retrooper.packetevents.wrapper.play.server.*; import dev.brighten.ac.data.APlayer; -import dev.brighten.ac.utils.BlockUtils; +import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.Materials; -import dev.brighten.ac.utils.XMaterial; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.world.types.RayCollision; -import io.github.retrooper.packetevents.util.SpigotConversionUtil; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import me.hydro.emulator.util.mcp.MathHelper; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; @Slf4j @SuppressWarnings("unused") @RequiredArgsConstructor public class BlockUpdateHandler { - // 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 Map worlds = new HashMap<>(); + @Getter + private AtomicReference currentWorld = new AtomicReference<>(); /** * Clear all chunks when the player changes worlds */ - public void onWorldChange() { - synchronized (chunks) { - java.util.Arrays.fill(chunks, null); - } + public void onRespawn(WrapperPlayServerRespawn respawn) { + respawn.getWorldName() + .filter(name -> !name.equals(currentWorld.get().getName())) + .ifPresent(worldName -> { + currentWorld.set(getWorldByName(worldName)); + player.getMob().despawn(); - setMinHeight(player.getDimensionType()); + player.runKeepaliveAction(ka -> { + KLocation origin = player.getMovement().getTo().getLoc().add(0, 1.7, 0); + + RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1)); + + Vector3d loc1 = coll.collisionPoint(1.2); + player.getMob().spawn(true, new KLocation(loc1), new ArrayList<>(), player); + }, 1); + }); + } + + private World getWorldByName(String name) { + return worlds.values().stream() + .filter(world -> world.getName().equals(name)) + .findFirst() + .orElse(worlds.put(name, new World(name))); } /** @@ -72,25 +73,30 @@ public class BlockUpdateHandler { public void onPlace(WrapperPlayClientPlayerBlockPlacement place) { player.getInfo().lastBlockUpdate.reset(); // Could not possibly be a block placement as it's not a block a player is holding. - IntVector pos = new IntVector(place.getBlockPosition()); + Vector3i pos = place.getBlockPosition(); // Some dumbass shit I have to do because Minecraft with Lilypads if (place.getItemStack().isPresent() - && BlockUtils.getXMaterial(place.getItemStack().get().getType()).equals(XMaterial.LILY_PAD)) { - RayCollision rayCollision = new RayCollision(player.getBukkitPlayer().getEyeLocation().toVector(), - player.getBukkitPlayer().getLocation().getDirection()); + && place.getItemStack().get().getType().equals(ItemTypes.LILY_PAD)) { + RayCollision rayCollision = new RayCollision(player.getMovement().getTo().getLoc() + .add(0, player.getEyeHeight(), 0).toVector(), + player.getMovement().getTo().getLoc().getDirection()); + //TODO Refactor this system to use just packetevents instead of this class WrappedBlock block = rayCollision.getClosestBlockOfType(player, Materials.LIQUID, 5); if (block != null) { - pos = new IntVector(block.getLocation().getX(), block.getLocation().getY() + 1, block.getLocation().getZ()); + pos = new Vector3i( + block.getLocation().getX(), + block.getLocation().getY() + 1, + block.getLocation().getZ()); } else return; } // Not an actual block place, just an interact else if (pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) { return; } else { - pos.setX(pos.getX() + place.getFace().getModX()); - pos.setY(pos.getY() + place.getFace().getModY()); - pos.setZ(pos.getZ() + place.getFace().getModZ()); + pos = pos.with(pos.getX() + place.getFace().getModX(), + pos.getY() + place.getFace().getModY(), + pos.getZ() + place.getFace().getModZ()); } player.getInfo().getLastPlace().reset(); @@ -100,220 +106,16 @@ public class BlockUpdateHandler { int y = pos.getY(); int z = pos.getZ(); - var placedType = place.getItemStack().get().getType().getPlacedType(); - if(place.getItemStack().isEmpty() || placedType == null) { + if(place.getItemStack().isEmpty() || place.getItemStack().get().getType().getPlacedType() == null) { return; } - updateBlock(x, y, z, WrappedBlockState.getDefaultState(placedType)); + currentWorld.get().updateBlock(x, y, z, + WrappedBlockState.getDefaultState(place.getItemStack().get().getType().getPlacedType())); } - /** - * Keep track of block diggings since the Bukkit API will be a bit behind - * @param x x coordinate - * @param z z coordinate - * @return the chunk at the specified coordinates - */ - public KColumn getChunk(int x, int z) { - 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()); - } + static final WrappedBlockState airBlockState = WrappedBlockState + .getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), 0); /** * Keep track of block breaking since the Bukkit API will be a bit behind. @@ -324,13 +126,13 @@ public class BlockUpdateHandler { player.getInfo().lastBlockUpdate.reset(); if (dig.getAction() == DiggingAction.FINISHED_DIGGING) { - IntVector pos = new IntVector(dig.getBlockPosition()); + Vector3i pos = dig.getBlockPosition(); if (pos.getX() == -1 && (pos.getY() == 255 || pos.getY() == -1) && pos.getZ() == -1) { return; } - updateBlock(pos.getX(), pos.getY(), pos.getZ(), airBlockState); + currentWorld.get().updateBlock(pos.getX(), pos.getY(), pos.getZ(), airBlockState); } } @@ -343,9 +145,9 @@ public class BlockUpdateHandler { // Updating block information player.runKeepaliveAction(k -> { - IntVector pos = new IntVector(packet.getBlockPosition()); + Vector3i pos = packet.getBlockPosition(); - updateBlock(pos.getX(), pos.getY(), pos.getZ(), packet.getBlockState()); + currentWorld.get().updateBlock(pos.getX(), pos.getY(), pos.getZ(), packet.getBlockState()); }); } @@ -358,41 +160,20 @@ public class BlockUpdateHandler { player.runKeepaliveAction(k -> { for (WrapperPlayServerMultiBlockChange.EncodedBlock info : packet.getBlocks()) { - WrappedBlockState blockState = info.getBlockState(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()); + WrappedBlockState blockState = info + .getBlockState(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion()); - updateBlock(info.getX(), info.getY(), info.getZ(), blockState); + currentWorld.get().updateBlock(info.getX(), info.getY(), info.getZ(), blockState); } }); } - private void updateBlock(int x, int y, int z, WrappedBlockState blockState) { - KColumn col = getChunk(x, z); - - int offset = y - minHeight; - - if(offset < 0 || (offset >> 4) > col.chunks().length) { - return; - } - - BaseChunk chunk = col.chunks()[offset >> 4]; - - if(chunk == null) { - chunk = create(); - col.chunks()[offset >> 4] = chunk; - - chunk.set(player.getPlayerVersion(), 0, 0, 0, 0); - } - - chunk.set(x & 15, offset & 15, z & 15, - blockState); - } - /** * Keep track of block updates since the Bukkit API will be a bit behind. * @param chunkUpdate Wrapped PacketPlayOutMapChunk */ public void runUpdate(WrapperPlayServerChunkData chunkUpdate) { - player.runKeepaliveAction(k -> updateChunk(chunkUpdate.getColumn())); + player.runKeepaliveAction(k -> currentWorld.get().updateChunk(chunkUpdate.getColumn())); } public void runUpdate(WrapperPlayServerChunkDataBulk chunkBulk) { @@ -403,9 +184,10 @@ public class BlockUpdateHandler { int x = chunkBulk.getX()[index]; int z = chunkBulk.getZ()[index]; - Column column = new Column(x, z, true, chunks, new TileEntity[0], chunkBulk.getBiomeData()[index]); + Column column = new Column(x, z, true, chunks, new TileEntity[0], + chunkBulk.getBiomeData()[index]); - updateChunk(column); + currentWorld.get().updateChunk(column); } }); } @@ -418,8 +200,8 @@ public class BlockUpdateHandler { * @param modZ the z modifier * @return the block relative to the specified location */ - public WrappedBlock getRelative(IntVector location, int modX, int modY, int modZ) { - return getBlock(location.clone().add(modX, modY, modZ)); + public WrappedBlock getRelative(Vector3i location, int modX, int modY, int modZ) { + return currentWorld.get().getBlock(location.add(modX, modY, modZ)); } /** @@ -429,7 +211,7 @@ public class BlockUpdateHandler { * @param distance the distance * @return the block relative to the specified location */ - public WrappedBlock getRelative(IntVector location, BlockFace face, int distance) { + public WrappedBlock getRelative(Vector3i location, BlockFace face, int distance) { return getRelative(location, face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance); } @@ -440,8 +222,20 @@ public class BlockUpdateHandler { * @param face the face * @return the block relative to the specified location */ - public WrappedBlock getRelative(IntVector location, BlockFace face) { - return getBlock(location.clone().add(face.getModX(), face.getModY(), face.getModZ())); + public WrappedBlock getRelative(Vector3i location, BlockFace face) { + return currentWorld.get().getBlock(location.add(face.getModX(), face.getModY(), face.getModZ())); + } + + public WrappedBlock getBlock(int x, int y, int z) { + return currentWorld.get().getBlock(x, y, z); + } + + public WrappedBlock getBlock(KLocation location) { + return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + public WrappedBlock getBlock(Vector3i location) { + return getBlock(location.getX(), location.getY(), location.getZ()); } public record KColumn(int x, int z, BaseChunk[] chunks) {} diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/block/Chunk.java b/Anticheat/src/main/java/dev/brighten/ac/handler/block/Chunk.java index 9544478..cca730f 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/block/Chunk.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/block/Chunk.java @@ -1,9 +1,11 @@ package dev.brighten.ac.handler.block; -import dev.brighten.ac.utils.math.IntVector; +import com.github.retrooper.packetevents.util.Vector3i; import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.Arrays; +import java.util.Objects; import java.util.Optional; @RequiredArgsConstructor @@ -17,7 +19,7 @@ public class Chunk { * @param location - Location of the block * @return Optional of the block at the specified location */ - public Optional getBlockAt(IntVector location) { + public Optional getBlockAt(Vector3i location) { return getBlockAt(location.getX(), location.getY(), location.getZ()); } @@ -64,7 +66,18 @@ public class Chunk { * @param location - Location of the block * @param block - Block to update to */ - public void updateBlock(IntVector location, WrappedBlock block) { + public void updateBlock(Vector3i location, WrappedBlock block) { updateBlock(location.getX(), location.getY(), location.getZ(), block); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Chunk chunk)) return false; + return x == chunk.x && z == chunk.z && Objects.deepEquals(blocks, chunk.blocks); + } + + @Override + public int hashCode() { + return Objects.hash(x, z, Arrays.deepHashCode(blocks)); + } } diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/block/World.java b/Anticheat/src/main/java/dev/brighten/ac/handler/block/World.java new file mode 100644 index 0000000..bcbeb4f --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/block/World.java @@ -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 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 getTrackedEntity(int entityId) { + TrackedEntity trackedEntity = trackedEntities.get(entityId); + + if(trackedEntity == null) { + return Optional.empty(); + } + + return Optional.of(trackedEntity); + } +} diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/block/WrappedBlock.java b/Anticheat/src/main/java/dev/brighten/ac/handler/block/WrappedBlock.java index 825143f..e62d334 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/block/WrappedBlock.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/block/WrappedBlock.java @@ -2,14 +2,14 @@ package dev.brighten.ac.handler.block; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; -import dev.brighten.ac.utils.math.IntVector; +import com.github.retrooper.packetevents.util.Vector3i; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public class WrappedBlock { - private IntVector location; + private Vector3i location; private StateType type; private WrappedBlockState blockState; } diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/entity/TrackedEntity.java b/Anticheat/src/main/java/dev/brighten/ac/handler/entity/TrackedEntity.java index a262e39..720b77e 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/entity/TrackedEntity.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/entity/TrackedEntity.java @@ -1,13 +1,19 @@ package dev.brighten.ac.handler.entity; +import com.github.retrooper.packetevents.protocol.attribute.Attribute; import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUpdateAttributes; +import dev.brighten.ac.data.obj.Pose; +import dev.brighten.ac.handler.ValuedAttribute; import dev.brighten.ac.utils.EntityLocation; import dev.brighten.ac.utils.KLocation; import lombok.Getter; import lombok.Setter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Getter @Setter @@ -17,6 +23,8 @@ public class TrackedEntity { private KLocation location; private EntityLocation oldEntityLocation, newEntityLocation; private List fakeMobs = new ArrayList<>(); + private Set attributes = new HashSet<>(); + private Pose pose = Pose.STANDING; public TrackedEntity(int entityId, EntityType entityType, KLocation location) { this.entityId = entityId; @@ -31,4 +39,30 @@ public class TrackedEntity { newEntityLocation.yaw = location.getYaw(); newEntityLocation.pitch = location.getPitch(); } + + public KLocation getEyeLocation() { + return new KLocation(location.getX(), location.getY() + pose.eyeHeight, location.getZ(), + location.getYaw(), location.getPitch()); + } + + public ValuedAttribute getAttribute(Attribute type) { + for(ValuedAttribute attribute : attributes) { + if(attribute.getAttribute().equals(type)) { + return attribute; + } + } + return null; + } + + public void updateAttribute(WrapperPlayServerUpdateAttributes.Property property) { + ValuedAttribute attribute = getAttribute(property.getAttribute()); + + if(attribute == null) { + attribute = new ValuedAttribute(property.getAttribute()); + } + + attribute.updateAttribute(property); + + attributes.add(attribute); + } } diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java b/Anticheat/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java index 341c1f9..5dff132 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/keepalive/KeepaliveProcessor.java @@ -49,7 +49,7 @@ public class KeepaliveProcessor { double dh = Math.min(value.getMovement().getDeltaXZ(), 1), dy = Math.min(1, Math.abs(value.getMovement().getDeltaY())); - value.getInfo().nearbyEntities = value.getEntityLocationHandler().getTrackedEntities().values() + value.getInfo().nearbyEntities = value.getWorldTracker().getCurrentWorld().get().getTrackedEntities().values() .stream() .filter(te -> te.getLocation().distance(value.getMovement().getTo().getLoc()) < (2 + (dh + dy) / 2)) diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/Protocol.java b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/Protocol.java index 430baf3..5ddabdc 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/Protocol.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/Protocol.java @@ -1,25 +1,8 @@ package dev.brighten.ac.handler.protocol; -import dev.brighten.ac.Anticheat; -import dev.brighten.ac.handler.protocol.impl.NoAPI; -import dev.brighten.ac.handler.protocol.impl.ProtocolSupport; -import dev.brighten.ac.handler.protocol.impl.ViaVersionAPI; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; + +import dev.brighten.ac.data.APlayer; public interface Protocol { - int getPlayerVersion(Player player); - - static Protocol getProtocol() { - if(Bukkit.getPluginManager().isPluginEnabled("ViaVersion")) { - Anticheat.INSTANCE.alog("Using ViaVersion for ProtocolAPI"); - return new ViaVersionAPI(); - } else if(Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport")) { - Anticheat.INSTANCE.alog("Using ProtocolSupport for ProtocolAPI"); - return new ProtocolSupport(); - } else { - Anticheat.INSTANCE.alog("Using Vanilla API for ProtocolAPI"); - return new NoAPI(); - } - } + int getPlayerVersion(APlayer player); } diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/NoAPI.java b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/NoAPI.java index a342ab4..df69446 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/NoAPI.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/NoAPI.java @@ -1,13 +1,13 @@ package dev.brighten.ac.handler.protocol.impl; import com.github.retrooper.packetevents.PacketEvents; +import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.protocol.Protocol; -import org.bukkit.entity.Player; public class NoAPI implements Protocol { @Override - public int getPlayerVersion(Player player) { - return PacketEvents.getAPI().getPlayerManager().getClientVersion(player).getProtocolVersion(); + public int getPlayerVersion(APlayer player) { + return PacketEvents.getAPI().getPlayerManager().getClientVersion(player.getBukkitPlayer()).getProtocolVersion(); } } diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ProtocolSupport.java b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ProtocolSupport.java deleted file mode 100644 index 68af03c..0000000 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ProtocolSupport.java +++ /dev/null @@ -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(); - } -} diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ViaVersionAPI.java b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ViaVersionAPI.java index 6c673a0..9de7802 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ViaVersionAPI.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/protocol/impl/ViaVersionAPI.java @@ -2,16 +2,16 @@ package dev.brighten.ac.handler.protocol.impl; import com.viaversion.viaversion.api.Via; import dev.brighten.ac.Anticheat; +import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.protocol.Protocol; -import org.bukkit.entity.Player; public class ViaVersionAPI implements Protocol { @Override - public int getPlayerVersion(Player player) { - Anticheat.INSTANCE.alog("Getting player version for " + player.getName()); - var toReturn = Via.getAPI().getPlayerVersion(player.getUniqueId()); - Anticheat.INSTANCE.alog("Player version for " + player.getName() + " is " + toReturn); + public int getPlayerVersion(APlayer player) { + Anticheat.INSTANCE.alog("Getting player version for " + player.getBukkitPlayer().getName()); + var toReturn = Via.getAPI().getPlayerVersion(player.getBukkitPlayer().getUniqueId()); + Anticheat.INSTANCE.alog("Player version for " + player.getBukkitPlayer().getName() + " is " + toReturn); return toReturn; } diff --git a/Anticheat/src/main/java/dev/brighten/ac/listener/GeneralListener.java b/Anticheat/src/main/java/dev/brighten/ac/listener/GeneralListener.java index 02d5c59..995c934 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/listener/GeneralListener.java +++ b/Anticheat/src/main/java/dev/brighten/ac/listener/GeneralListener.java @@ -1,5 +1,6 @@ package dev.brighten.ac.listener; +import com.github.retrooper.packetevents.util.Vector3d; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.utils.KLocation; @@ -68,14 +69,15 @@ public class GeneralListener implements Listener { Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId()) .ifPresent(player -> { - player.getBlockUpdateHandler().onWorldChange(); // Updating bot loc when changing worlds Location origin = event.getTo().clone().add(0, 1.7, 0); + Vector mult = origin.getDirection().multiply(-1); - RayCollision coll = new RayCollision(origin.toVector(), origin.getDirection().multiply(-1)); + RayCollision coll = new RayCollision(new Vector3d(origin.getX(), origin.getY(), origin.getZ()), + new Vector3d(mult.getX(), mult.getY(), mult.getZ())); - Vector loc1 = coll.collisionPoint(1.2); + Vector3d loc1 = coll.collisionPoint(1.2); Anticheat.INSTANCE.getRunUtils().taskLater(() -> { player.getMob().despawn(); diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java b/Anticheat/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java index 6bfa239..6cca6f8 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/AxisAlignedBB.java @@ -1,6 +1,7 @@ package dev.brighten.ac.utils; import com.github.retrooper.packetevents.protocol.world.Direction; +import com.github.retrooper.packetevents.util.Vector3d; import dev.brighten.ac.utils.world.types.RayCollision; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import org.bukkit.Location; @@ -211,6 +212,14 @@ public class AxisAlignedBB { return rayTrace(origin, dir); } + public Vec3D rayTrace(Vector3d vorigin, Vector3d vdirection, double distance) { + Vec3D origin = new Vec3D(vorigin.getX(), vorigin.getY(), vorigin.getZ()); + Vector3d direction = vdirection.multiply(distance); + Vec3D dir = origin.clone().add(direction.getX(), direction.getY(), direction.getZ()); + + return rayTrace(origin, dir); + } + public Vec3D rayTrace(Vec3D vec3d, Vec3D vec3d1) { Vec3D vec3d2 = vec3d.a(vec3d1, this.minX); Vec3D vec3d3 = vec3d.a(vec3d1, this.maxX); diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/BlockUtils.java b/Anticheat/src/main/java/dev/brighten/ac/utils/BlockUtils.java index 481fade..30ae217 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/BlockUtils.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/BlockUtils.java @@ -2,19 +2,18 @@ package dev.brighten.ac.utils; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.item.type.ItemType; +import com.github.retrooper.packetevents.protocol.item.type.ItemTypes; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; +import com.github.retrooper.packetevents.util.Vector3i; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.handler.entity.TrackedEntity; -import dev.brighten.ac.utils.math.IntVector; import io.github.retrooper.packetevents.util.SpigotConversionUtil; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Vehicle; import java.util.EnumMap; import java.util.EnumSet; @@ -84,20 +83,20 @@ public class BlockUtils { return Optional.empty(); } - public static Optional getRelative(APlayer player, IntVector location, int modX, int modY, int modZ) { - return Optional.of(player.getBlockUpdateHandler() - .getRelative(new IntVector(location.getX(), location.getY(), location.getZ()), + public static Optional getRelative(APlayer player, Vector3i location, int modX, int modY, int modZ) { + return Optional.of(player.getWorldTracker() + .getRelative(new Vector3i(location.getX(), location.getY(), location.getZ()), modX, modY, modZ)); } - public static Optional getRelative(APlayer player, IntVector location, + public static Optional getRelative(APlayer player, Vector3i location, com.github.retrooper.packetevents.protocol.world .BlockFace face, int distance) { return getRelative(player, location, face.getModX() * distance, face.getModY() * distance, face.getModZ() * distance); } - public static Optional getRelative(APlayer player, IntVector vector, BlockFace face) { + public static Optional getRelative(APlayer player, Vector3i vector, BlockFace face) { return getRelative(player, vector, face.getModX(), face.getModY(), face.getModZ()); } @@ -134,6 +133,12 @@ public class BlockUtils { return isUsable(getXMaterial(material)); } + public static boolean isUsable(ClientVersion version, ItemType type) { + return type.hasAttribute(ItemTypes.ItemAttribute.EDIBLE) + || (version.isOlderThan(ClientVersion.V_1_9) && type.hasAttribute(ItemTypes.ItemAttribute.SWORD)) + || type.equals(ItemTypes.SHIELD); + } + public static boolean isUsable(XMaterial xmaterial) { if(XEDIBLE.contains(xmaterial)) return true; return switch (xmaterial) { diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/Helper.java b/Anticheat/src/main/java/dev/brighten/ac/utils/Helper.java index 582fae9..7e85488 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/Helper.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/Helper.java @@ -1,16 +1,15 @@ package dev.brighten.ac.utils; -import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.particle.Particle; import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; import com.github.retrooper.packetevents.util.Vector3d; import com.github.retrooper.packetevents.util.Vector3f; +import com.github.retrooper.packetevents.util.Vector3i; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerParticle; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.entity.TrackedEntity; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.world.BlockData; import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.EntityData; @@ -137,8 +136,8 @@ public class Helper { for (int x = x1; x < x2; ++x) for (int y = y1 - 1; y < y2; ++y) for (int z = z1; z < z2; ++z) { - IntVector vec = new IntVector(x, y, z); - StateType type = player.getBlockUpdateHandler().getBlock(vec).getType(); + Vector3i vec = new Vector3i(x, y, z); + StateType type = player.getWorldTracker().getBlock(vec).getType(); if (type != StateTypes.AIR && (mask == -100 || Materials.checkFlag(type, mask))) { CollisionBox box = BlockData.getData(type) diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/KPotionEffect.java b/Anticheat/src/main/java/dev/brighten/ac/utils/KPotionEffect.java new file mode 100644 index 0000000..7deaa79 --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/KPotionEffect.java @@ -0,0 +1,7 @@ +package dev.brighten.ac.utils; + +import com.github.retrooper.packetevents.protocol.potion.PotionType; + +public record KPotionEffect(PotionType potionType, KProperties properties) { + +} \ No newline at end of file diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/KProperties.java b/Anticheat/src/main/java/dev/brighten/ac/utils/KProperties.java new file mode 100644 index 0000000..e27e092 --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/KProperties.java @@ -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); + } +} \ No newline at end of file diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/Materials.java b/Anticheat/src/main/java/dev/brighten/ac/utils/Materials.java index 24c1293..7138f36 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/Materials.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/Materials.java @@ -9,6 +9,7 @@ import org.bukkit.Material; import java.util.HashMap; import java.util.Map; +//TODO Refactor this system to use just packetevents instead of this class public class Materials { private static final Map MATERIAL_FLAGS = new HashMap<>(); @@ -31,11 +32,11 @@ public class Materials { int flag = MATERIAL_FLAGS.getOrDefault(mat, 0); //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; } - if(!(BlockData.getData(mat).getDefaultBox() instanceof NoCollisionBox)) { + if(!(BlockData.getData(mat).getDefaultBox() instanceof NoCollisionBox) || mat.isBlocking()) { flag |= COLLIDABLE; } diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/MiscUtils.java b/Anticheat/src/main/java/dev/brighten/ac/utils/MiscUtils.java index e4698a2..a582a8c 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/MiscUtils.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/MiscUtils.java @@ -58,7 +58,7 @@ public class MiscUtils { for(int x = startX ; x < endX ; x++) { for(int y = startY ; y < endY ; y++) { for(int z = startZ ; z < endZ ; z++) { - StateType type = player.getBlockUpdateHandler().getBlock(x, y, z).getType(); + StateType type = player.getWorldTracker().getBlock(x, y, z).getType(); if(Materials.checkFlag(type, bitmask)) return true; diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/MovementUtils.java b/Anticheat/src/main/java/dev/brighten/ac/utils/MovementUtils.java index 4880bcf..fbfcf63 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/MovementUtils.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/MovementUtils.java @@ -19,7 +19,7 @@ public class MovementUtils { public static double getJumpHeight(APlayer data) { float baseHeight = 0.42f; - baseHeight+= data.getInfo().groundJumpBoost.map(ef -> ef.getAmplifier() + 1) + baseHeight+= data.getInfo().groundJumpBoost.map(ef -> ef.properties().amplifier() + 1) .orElse(0) * 0.1f; return baseHeight; @@ -38,7 +38,7 @@ public class MovementUtils { int i = MathHelper.floor_double(data.getMovement().getTo().getLoc().getX()); int j = MathHelper.floor_double(data.getMovement().getTo().getBox().minY); int k = MathHelper.floor_double(data.getMovement().getTo().getLoc().getZ()); - WrappedBlock block = data.getBlockUpdateHandler().getBlock(i, j, k); + WrappedBlock block = data.getWorldTracker().getBlock(i, j, k); return Materials.checkFlag(block.getType(), Materials.LADDER); diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/math/IntVector.java b/Anticheat/src/main/java/dev/brighten/ac/utils/math/IntVector.java index 926f535..848df47 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/math/IntVector.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/math/IntVector.java @@ -54,6 +54,10 @@ public class IntVector implements Cloneable { return new Vector(x, y, z); } + public Vector3i toVector3i() { + return new Vector3i(x, y, z); + } + @Override public String toString() { return "[" + x + ", " + y + ", " + z + "]"; diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/math/RayTrace.java b/Anticheat/src/main/java/dev/brighten/ac/utils/math/RayTrace.java index adecee7..b1e4ddb 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/math/RayTrace.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/math/RayTrace.java @@ -2,11 +2,14 @@ package dev.brighten.ac.utils.math; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.manager.server.ServerVersion; +import com.github.retrooper.packetevents.util.Vector3d; +import dev.brighten.ac.utils.KLocation; +import dev.brighten.ac.utils.MathUtils; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import org.bukkit.Effect; +import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.List; @@ -15,15 +18,15 @@ public class RayTrace { //origin = start position //direction = direction in which the raytrace will go - Vector origin, direction; + Vector3d origin, direction; - public RayTrace(Vector origin, Vector direction) { + public RayTrace(Vector3d origin, Vector3d direction) { this.origin = origin; this.direction = direction; } //general intersection detection - public static boolean intersects(Vector position, Vector min, Vector max) { + public static boolean intersects(Vector3d position, Vector3d min, Vector3d max) { if (position.getX() < min.getX() || position.getX() > max.getX()) { return false; } else if (position.getY() < min.getY() || position.getY() > max.getY()) { @@ -32,27 +35,27 @@ public class RayTrace { } //get a point on the raytrace at X blocks away - public Vector getPostion(double blocksAway) { - return origin.clone().add(direction.clone().multiply(blocksAway)); + public Vector3d getPostion(double blocksAway) { + return origin.add(direction.multiply(blocksAway)); } //checks if a position is on contained within the position - public boolean isOnLine(Vector position) { + public boolean isOnLine(Vector3d position) { double t = (position.getX() - origin.getX()) / direction.getX(); - return position.getBlockY() == origin.getY() + (t * direction.getY()) && position.getBlockZ() == origin.getZ() + (t * direction.getZ()); + return MathUtils.floor(position.getY()) == origin.getY() + (t * direction.getY()) && MathUtils.floor(position.getZ()) == origin.getZ() + (t * direction.getZ()); } //get all postions on a raytrace - public List traverse(double blocksAway, double accuracy) { - List positions = new ArrayList<>(); + public List traverse(double blocksAway, double accuracy) { + List positions = new ArrayList<>(); for (double d = 0; d <= blocksAway; d += accuracy) { positions.add(getPostion(d)); } return positions; } - public List traverse(double skip, double blocksAway, double accuracy) { - List positions = new ArrayList<>(); + public List traverse(double skip, double blocksAway, double accuracy) { + List positions = new ArrayList<>(); for (double d = skip; d <= blocksAway; d += accuracy) { positions.add(getPostion(d)); } @@ -62,14 +65,17 @@ public class RayTrace { public List getBlocks(World world, double blocksAway, double accuracy) { List blocks = new ArrayList<>(); - traverse(blocksAway, accuracy).stream().filter(vector -> vector.toLocation(world).getBlock().getType().isSolid()).forEach(vector -> blocks.add(vector.toLocation(world).getBlock())); + traverse(blocksAway, accuracy).stream() + .map(KLocation::new) + .filter(vector -> vector.toLocation(world).getBlock().getType().isSolid()) + .forEach(vector -> blocks.add(vector.toLocation(world).getBlock())); return blocks; } //intersection detection for current raytrace with return - public Vector positionOfIntersection(Vector min, Vector max, double blocksAway, double accuracy) { - List positions = traverse(blocksAway, accuracy); - for (Vector position : positions) { + public Vector3d positionOfIntersection(Vector3d min, Vector3d max, double blocksAway, double accuracy) { + List positions = traverse(blocksAway, accuracy); + for (Vector3d position : positions) { if (intersects(position, min, max)) { return position; } @@ -78,9 +84,9 @@ public class RayTrace { } //intersection detection for current raytrace - public boolean intersects(Vector min, Vector max, double blocksAway, double accuracy) { - List positions = traverse(blocksAway, accuracy); - for (Vector position : positions) { + public boolean intersects(Vector3d min, Vector3d max, double blocksAway, double accuracy) { + List positions = traverse(blocksAway, accuracy); + for (Vector3d position : positions) { if (intersects(position, min, max)) { return true; } @@ -89,9 +95,9 @@ public class RayTrace { } //bounding blockbox instead of vector - public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) { - List positions = traverse(blocksAway, accuracy); - for (Vector position : positions) { + public Vector3d positionOfIntersection(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) { + List positions = traverse(blocksAway, accuracy); + for (Vector3d position : positions) { if (intersects(position, collisionBox.min(), collisionBox.max())) { return position; } @@ -99,9 +105,9 @@ public class RayTrace { return null; } - public Vector positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) { - List positions = traverse(skip, blocksAway, accuracy); - for (Vector position : positions) { + public Vector3d positionOfIntersection(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) { + List positions = traverse(skip, blocksAway, accuracy); + for (Vector3d position : positions) { if (intersects(position, collisionBox.min(), collisionBox.max())) { return position; } @@ -111,8 +117,8 @@ public class RayTrace { //bounding blockbox instead of vector public boolean intersects(SimpleCollisionBox collisionBox, double blocksAway, double accuracy) { - List positions = traverse(blocksAway, accuracy); - for (Vector position : positions) { + List positions = traverse(blocksAway, accuracy); + for (Vector3d position : positions) { if (intersects(position, collisionBox.min(), collisionBox.max())) { return true; } @@ -121,8 +127,8 @@ public class RayTrace { } public boolean intersects(SimpleCollisionBox collisionBox, double skip, double blocksAway, double accuracy) { - List positions = traverse(blocksAway, accuracy); - for (Vector position : positions) { + List positions = traverse(blocksAway, accuracy); + for (Vector3d position : positions) { if (intersects(position, collisionBox.min(), collisionBox.max())) { return true; } @@ -132,8 +138,8 @@ public class RayTrace { //debug / effects public void highlight(World world, double blocksAway, double accuracy) { - for (Vector position : traverse(blocksAway, accuracy)) { - world.playEffect(position.toLocation(world), (PacketEvents.getAPI().getServerManager().getVersion() + for (Vector3d position : traverse(blocksAway, accuracy)) { + world.playEffect(new Location(world, position.x, position.y, position.z), (PacketEvents.getAPI().getServerManager().getVersion() .isNewerThanOrEquals(ServerVersion.V_1_13) ? Effect.SMOKE : Effect.valueOf("COLOURED_DUST")), 0); } } diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/world/BlockData.java b/Anticheat/src/main/java/dev/brighten/ac/utils/world/BlockData.java index 4dd306c..928d396 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/world/BlockData.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/world/BlockData.java @@ -8,10 +8,10 @@ import com.github.retrooper.packetevents.protocol.world.states.defaulttags.Block import com.github.retrooper.packetevents.protocol.world.states.enums.*; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; +import com.github.retrooper.packetevents.util.Vector3i; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.block.WrappedBlock; import dev.brighten.ac.utils.BlockUtils; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.world.blocks.*; import dev.brighten.ac.utils.world.types.*; @@ -110,12 +110,58 @@ public enum BlockData { _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) -> { double f1 = (1 + block.getBlockState().getBites() * 2) / 16D; return new SimpleCollisionBox(f1, 0, 0.0625, 1 - 0.0625, 0.5, 1 - 0.0625); }, 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) -> { int age = block.getBlockState().getAge(); if (protocol.isNewerThanOrEquals(ClientVersion.V_1_9_1) && protocol.isOlderThan(ClientVersion.V_1_11)) @@ -282,7 +328,34 @@ public enum BlockData { StateTypes.STRUCTURE_VOID), _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, 1 - 0.0625, 1 - 0.0625, 1 - 0.0625), StateTypes.CACTUS), _PISTON_BASE(new PistonBaseCollision(), StateTypes.PISTON, StateTypes.STICKY_PISTON), @@ -304,6 +377,67 @@ public enum BlockData { }, StateTypes.LECTERN), _POT(new SimpleCollisionBox(0.3125, 0.0, 0.3125, 0.6875, 0.375, 0.6875), 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, 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); } - public CollisionBox getBox(APlayer player, IntVector block, ClientVersion version) { + public CollisionBox getBox(APlayer player, Vector3i block, ClientVersion version) { if (this.box != null) return this.box.copy().offset(block.getX(), block.getY(), block.getZ()); - return new DynamicCollisionBox(dynamic, player, player.getBlockUpdateHandler().getBlock(block), version) + return new DynamicCollisionBox(dynamic, player, player.getWorldTracker().getBlock(block), version) .offset(block.getX(), block.getY(), block.getZ()); } diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/world/EntityData.java b/Anticheat/src/main/java/dev/brighten/ac/utils/world/EntityData.java index 2461fa0..f5fc976 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/world/EntityData.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/world/EntityData.java @@ -3,6 +3,7 @@ package dev.brighten.ac.utils.world; import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import dev.brighten.ac.handler.entity.TrackedEntity; +import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.world.types.NoCollisionBox; import dev.brighten.ac.utils.world.types.SimpleCollisionBox; import org.bukkit.Location; @@ -23,6 +24,10 @@ public class EntityData { return bounds(entity.getEntityType()).offset(location.getX(), location.getY(), location.getZ()); } + public static CollisionBox getEntityBox(KLocation location, TrackedEntity entity) { + return bounds(entity.getEntityType()).offset(location.getX(), location.getY(), location.getZ()); + } + public static CollisionBox getEntityBox(Location location, EntityType entity) { return bounds(entity).offset(location.getX(), location.getY(), location.getZ()); } diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DoorHandler.java b/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DoorHandler.java index 835fceb..ccda36f 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DoorHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DoorHandler.java @@ -7,9 +7,9 @@ import com.github.retrooper.packetevents.protocol.world.BlockFace; import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState; import com.github.retrooper.packetevents.protocol.world.states.enums.Half; import com.github.retrooper.packetevents.protocol.world.states.enums.Hinge; +import com.github.retrooper.packetevents.util.Vector3i; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.block.WrappedBlock; -import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.world.CollisionBox; import dev.brighten.ac.utils.world.types.CollisionFactory; import dev.brighten.ac.utils.world.types.HexCollisionBox; @@ -50,10 +50,10 @@ public class DoorHandler implements CollisionFactory { if (PacketEvents.getAPI().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_12_2) || version.isOlderThanOrEquals(ClientVersion.V_1_12_2)) { if (door.getBlockState().getHalf() == Half.LOWER) { - IntVector aboveVec = door.getLocation().clone(); + Vector3i aboveVec = door.getLocation(); - aboveVec.setY(aboveVec.getY() + 1); - WrappedBlockState above = player.getBlockUpdateHandler().getBlock(aboveVec).getBlockState(); + aboveVec = aboveVec.add(0, aboveVec.getY() + 1, 0); + WrappedBlockState above = player.getWorldTracker().getBlock(aboveVec).getBlockState(); facingDirection = door.getBlockState().getFacing(); isClosed = !door.getBlockState().isOpen(); @@ -67,10 +67,10 @@ public class DoorHandler implements CollisionFactory { isRightHinge = false; } } else { - IntVector belowVec = door.getLocation().clone(); + Vector3i belowVec = door.getLocation(); - belowVec.setY(belowVec.getY() - 1); - WrappedBlockState below = player.getBlockUpdateHandler().getBlock(belowVec).getBlockState(); + belowVec = belowVec.add(0, belowVec.getY() - 1, 0); + WrappedBlockState below = player.getWorldTracker().getBlock(belowVec).getBlockState(); if (below.getType() == door.getBlockState().getType() && below.getHalf() == Half.LOWER) { isClosed = !below.isOpen(); diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DynamicStair.java b/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DynamicStair.java index 9ef65aa..127f060 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DynamicStair.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/world/blocks/DynamicStair.java @@ -44,7 +44,7 @@ public class DynamicStair implements CollisionFactory { z = originalStairs.getLocation().getZ(); WrappedBlock offsetOne = player == null ? null - : player.getBlockUpdateHandler().getBlock( + : player.getWorldTracker().getBlock( x + facing.getModX(), y + facing.getModY(), z + facing.getModZ()); @@ -64,7 +64,7 @@ public class DynamicStair implements CollisionFactory { } } - WrappedBlock offsetTwo = player.getBlockUpdateHandler() + WrappedBlock offsetTwo = player.getWorldTracker() .getBlock(x + facing.getOppositeFace().getModX(), y + facing.getOppositeFace().getModY(), z + facing.getOppositeFace().getModZ()); diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java b/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java index 6892315..0ca462f 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/RayCollision.java @@ -4,18 +4,18 @@ import com.github.retrooper.packetevents.PacketEvents; import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; import com.github.retrooper.packetevents.protocol.player.ClientVersion; import com.github.retrooper.packetevents.protocol.world.states.type.StateType; +import com.github.retrooper.packetevents.util.Vector3d; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.block.WrappedBlock; +import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.utils.Helper; +import dev.brighten.ac.utils.KLocation; import dev.brighten.ac.utils.Materials; import dev.brighten.ac.utils.Tuple; import dev.brighten.ac.utils.math.RayTrace; import dev.brighten.ac.utils.world.BlockData; import dev.brighten.ac.utils.world.CollisionBox; import me.hydro.emulator.util.mcp.MathHelper; -import org.bukkit.Location; -import org.bukkit.entity.LivingEntity; -import org.bukkit.util.Vector; import java.util.ArrayList; import java.util.Arrays; @@ -58,15 +58,15 @@ public class RayCollision implements CollisionBox { directionZ = 0; } - public RayCollision(LivingEntity e) { + public RayCollision(TrackedEntity e) { this(e.getEyeLocation()); } - public RayCollision(Location l) { + public RayCollision(KLocation l) { this(l.toVector(),l.getDirection()); } - public RayCollision(Vector position, Vector direction) { + public RayCollision(Vector3d position, Vector3d direction) { this.originX = position.getX(); this.originY = position.getY(); this.originZ = position.getZ(); @@ -75,17 +75,17 @@ public class RayCollision implements CollisionBox { this.directionZ = direction.getZ(); } - public Vector getOrigin() { - return new Vector(originX, originY, originZ); + public Vector3d getOrigin() { + return new Vector3d(originX, originY, originZ); } - public Vector getDirection() { - return new Vector(directionX, directionY, directionZ); + public Vector3d getDirection() { + return new Vector3d(directionX, directionY, directionZ); } @Override public boolean isCollided(CollisionBox other) { - if (other instanceof RayCollision) { + if (other instanceof RayCollision) { return false; // lol no support } else { List boxes = new ArrayList<>(); @@ -141,7 +141,7 @@ public class RayCollision implements CollisionBox { public List boxesOnRay(APlayer player, double distance) { int amount = Math.round((float) (distance / 0.5)); - Location[] locs = new Location[Math.max(2, amount)]; //We do a max to prevent NegativeArraySizeException. + KLocation[] locs = new KLocation[Math.max(2, amount)]; //We do a max to prevent NegativeArraySizeException. List boxes = new ArrayList<>(); ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); @@ -152,7 +152,7 @@ public class RayCollision implements CollisionBox { int fy = MathHelper.floor_double(originY + (directionY * ix)); int fz = MathHelper.floor_double(originZ + (directionZ * ix)); - WrappedBlock block = player.getBlockUpdateHandler().getBlock(fx, fy, fz); + WrappedBlock block = player.getWorldTracker().getBlock(fx, fy, fz); if (block == null) continue; @@ -173,7 +173,7 @@ public class RayCollision implements CollisionBox { public WrappedBlock getClosestBlockOfType(APlayer player, int bitmask, double distance) { int amount = Math.round((float) (distance / 0.5)); - Location[] locs = new Location[Math.max(2, amount)]; //We do a max + KLocation[] locs = new KLocation[Math.max(2, amount)]; //We do a max ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(); for (int i = 0; i < locs.length; i++) { @@ -183,7 +183,7 @@ public class RayCollision implements CollisionBox { int fy = MathHelper.floor_double(originY + (directionY * ix)); int fz = MathHelper.floor_double(originZ + (directionZ * ix)); - WrappedBlock block = player.getBlockUpdateHandler().getBlock(fx, fy, fz); + WrappedBlock block = player.getWorldTracker().getBlock(fx, fy, fz); if(block == null || !Materials.checkFlag(block.getType(), bitmask)) continue; @@ -228,7 +228,7 @@ public class RayCollision implements CollisionBox { RayTrace trace = new RayTrace(ray.getOrigin(), ray.getDirection()); - Vector point = trace.positionOfIntersection(box, Math.max(0, dist - range), 0.01); + Vector3d point = trace.positionOfIntersection(box, Math.max(0, dist - range), 0.01); return ray.getOrigin().distance(point); } @@ -347,23 +347,23 @@ public class RayCollision implements CollisionBox { } } - public Vector collisionPoint(SimpleCollisionBox box) { + public Vector3d collisionPoint(SimpleCollisionBox box) { Tuple p = new Tuple<>(); if (box==null||!intersect(this,box,p)) return null; - Vector vector = new Vector(directionX,directionY,directionZ); + Vector3d vector = new Vector3d(directionX,directionY,directionZ); vector.normalize(); vector.multiply(p.one); - vector.add(new Vector(originX,originY,originZ)); + vector.add(new Vector3d(originX,originY,originZ)); return vector; } - public Vector collisionPoint(double dist) { - Vector vector = new Vector(directionX,directionY,directionZ); + public Vector3d collisionPoint(double dist) { + Vector3d vector = new Vector3d(directionX,directionY,directionZ); vector.normalize(); vector.multiply(dist); - vector.add(new Vector(originX,originY,originZ)); + vector.add(new Vector3d(originX,originY,originZ)); return vector; } - + } \ No newline at end of file diff --git a/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java b/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java index efe4194..04ef33a 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java +++ b/Anticheat/src/main/java/dev/brighten/ac/utils/world/types/SimpleCollisionBox.java @@ -1,6 +1,7 @@ package dev.brighten.ac.utils.world.types; import com.github.retrooper.packetevents.protocol.particle.type.ParticleType; +import com.github.retrooper.packetevents.util.Vector3d; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.utils.Helper; import dev.brighten.ac.utils.KLocation; @@ -54,7 +55,7 @@ public class SimpleCollisionBox implements CollisionBox { maxZ = width / 2; } - public SimpleCollisionBox(Vector min, Vector max) { + public SimpleCollisionBox(Vector3d min, Vector3d max) { this(min.getX(), min.getY(), min.getZ(), max.getX(), max.getY(), max.getZ()); } @@ -76,6 +77,13 @@ public class SimpleCollisionBox implements CollisionBox { maxY += height; } + public SimpleCollisionBox(Vector3d vec, double width, double height) { + this(vec.getX(), vec.getY(), vec.getZ(), vec.getX(), vec.getY(), vec.getZ()); + + expand(width / 2, 0, width / 2); + maxY += height; + } + public void sort() { double temp; if (minX >= maxX) { @@ -196,26 +204,26 @@ public class SimpleCollisionBox implements CollisionBox { return this; } - public Vector[] corners() { + public Vector3d[] corners() { sort(); - Vector[] vectors = new Vector[8]; - vectors[0] = new Vector(minX, minY, minZ); - vectors[1] = new Vector(minX, minY, maxZ); - vectors[2] = new Vector(maxX, minY, minZ); - vectors[3] = new Vector(maxX, minY, maxZ); - vectors[4] = new Vector(minX, maxY, minZ); - vectors[5] = new Vector(minX, maxY, maxZ); - vectors[6] = new Vector(maxX, maxY, minZ); - vectors[7] = new Vector(maxX, maxY, maxZ); + Vector3d[] vectors = new Vector3d[8]; + vectors[0] = new Vector3d(minX, minY, minZ); + vectors[1] = new Vector3d(minX, minY, maxZ); + vectors[2] = new Vector3d(maxX, minY, minZ); + vectors[3] = new Vector3d(maxX, minY, maxZ); + vectors[4] = new Vector3d(minX, maxY, minZ); + vectors[5] = new Vector3d(minX, maxY, maxZ); + vectors[6] = new Vector3d(maxX, maxY, minZ); + vectors[7] = new Vector3d(maxX, maxY, maxZ); return vectors; } - public Vector min() { - return new Vector(minX, minY, minZ); + public Vector3d min() { + return new Vector3d(minX, minY, minZ); } - public Vector max() { - return new Vector(maxX, maxY, maxZ); + public Vector3d max() { + return new Vector3d(maxX, maxY, maxZ); } @Override diff --git a/Compat/src/main/java/dev/brighten/ac/utils/KLocation.java b/Compat/src/main/java/dev/brighten/ac/utils/KLocation.java index f192fa9..a898c87 100644 --- a/Compat/src/main/java/dev/brighten/ac/utils/KLocation.java +++ b/Compat/src/main/java/dev/brighten/ac/utils/KLocation.java @@ -1,11 +1,11 @@ package dev.brighten.ac.utils; +import com.github.retrooper.packetevents.util.MathUtil; import com.github.retrooper.packetevents.util.Vector3d; +import com.github.retrooper.packetevents.util.Vector3i; import lombok.Data; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.util.Vector; -import org.joml.Vector2d; import java.util.Objects; @@ -41,14 +41,18 @@ public class KLocation implements Cloneable { this.timeStamp = System.currentTimeMillis(); } - public KLocation(Vector vector) { + public KLocation(Location location) { + this(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + } + + public KLocation(Vector3d vector) { this.x = vector.getX(); this.y = vector.getY(); this.z = vector.getZ(); this.timeStamp = System.currentTimeMillis(); } - public KLocation(Location location) { + public KLocation(KLocation location) { this.x = location.getX(); this.y = location.getY(); this.z = location.getZ(); @@ -57,12 +61,12 @@ public class KLocation implements Cloneable { this.timeStamp = System.currentTimeMillis(); } - public Vector toVector() { - return new Vector(x, y, z); + public Vector3d toVector() { + return new Vector3d(x, y, z); } - public Vector3d toVector3d() { - return new Vector3d(x, y, z); + public Vector3i toVector3i() { + return new Vector3i((int) x, (int) y, (int) z); } public Location toLocation(World world) { @@ -112,8 +116,27 @@ public class KLocation implements Cloneable { return this; } - public Vector getDirection() { - return MathUtils.getDirection(this); + public Vector3d getDirection() { + double rotX = this.getYaw(); + double rotY = this.getPitch(); + double x, y, z; + y = -Math.sin(Math.toRadians(rotY)); + double xz = Math.cos(Math.toRadians(rotY)); + x = -xz * Math.sin(Math.toRadians(rotX)); + z = xz * Math.cos(Math.toRadians(rotX)); + return new Vector3d(x, y, z); + } + + public int getBlockX() { + return MathUtil.floor(x); + } + + public int getBlockY() { + return MathUtil.floor(y); + } + + public int getBlockZ() { + return MathUtil.floor(z); } @Override diff --git a/Compat/src/main/java/dev/brighten/ac/utils/MathUtils.java b/Compat/src/main/java/dev/brighten/ac/utils/MathUtils.java index f228493..5d470e1 100644 --- a/Compat/src/main/java/dev/brighten/ac/utils/MathUtils.java +++ b/Compat/src/main/java/dev/brighten/ac/utils/MathUtils.java @@ -1,5 +1,6 @@ package dev.brighten.ac.utils; +import com.github.retrooper.packetevents.util.Vector3d; import lombok.val; import me.hydro.emulator.util.mcp.MathHelper; import org.bukkit.Location; @@ -196,10 +197,6 @@ public class MathUtils { return MathUtils.yawTo180D(playerRotation.getX() - expectedRotation.getX()); } - public static double getAngle(KLocation loc1, KLocation loc2) { - return getAngle(loc1.toLocation(null), loc2.toLocation(null)); - } - public static float distanceBetweenAngles(float a, float b) { final float first = a % 360; final float second = b % 360; @@ -544,16 +541,14 @@ public class MathUtils { return (short) num; } - /* Stolen from Bukkit */ - public static Vector getDirection(KLocation loc) { - Vector vector = new Vector(); + public static Vector3d getDirection(KLocation loc) { + Vector3d vector = new Vector3d(); double rotX = loc.getYaw(); double rotY = loc.getPitch(); - vector.setY(-Math.sin(Math.toRadians(rotY))); double xz = Math.cos(Math.toRadians(rotY)); - vector.setX(-xz * Math.sin(Math.toRadians(rotX))); - vector.setZ(xz * Math.cos(Math.toRadians(rotX))); - return vector; + return new Vector3d(-xz * Math.sin(Math.toRadians(rotX)), + -Math.sin(Math.toRadians(rotY)), + xz * Math.cos(Math.toRadians(rotX))); } @@ -704,12 +699,12 @@ public class MathUtils { return squareRoot; } - public static Vector getDirection(float yaw, float pitch) { + public static Vector3d getDirection(float yaw, float pitch) { float f = MathHelper.cos(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI); float f1 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -yaw * 0.017453292F - (float)Math.PI); float f2 = -MathHelper.cos(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F); float f3 = MathHelper.sin(MathHelper.FastMathType.VANILLA, -pitch * 0.017453292F); - return new Vector(f1 * f2, f3, f * f2); + return new Vector3d(f1 * f2, f3, f * f2); } public static float sqrt(float number) { diff --git a/Neo b/Neo index b45b76d..feb7913 160000 --- a/Neo +++ b/Neo @@ -1 +1 @@ -Subproject commit b45b76d09d92675324d727912bddc8971f53a014 +Subproject commit feb79131a2687d16eeb6320ada414272f50daf1e diff --git a/pom.xml b/pom.xml index f6fefa4..4a48a01 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,10 @@ + + maven-central + https://nexus.funkemunky.cc/repository/maven-central/ + spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/