diff --git a/API/src/main/java/dev/brighten/ac/api/check/CheckType.java b/API/src/main/java/dev/brighten/ac/api/check/CheckType.java index abe7f9b..16e2e77 100644 --- a/API/src/main/java/dev/brighten/ac/api/check/CheckType.java +++ b/API/src/main/java/dev/brighten/ac/api/check/CheckType.java @@ -3,6 +3,7 @@ package dev.brighten.ac.api.check; public enum CheckType { COMBAT, AUTOCLICKER, + KILLAURA, MOVEMENT, BLOCK, CHAT, diff --git a/src/main/java/dev/brighten/ac/check/Check.java b/src/main/java/dev/brighten/ac/check/Check.java index 5aff325..0e2e347 100644 --- a/src/main/java/dev/brighten/ac/check/Check.java +++ b/src/main/java/dev/brighten/ac/check/Check.java @@ -11,7 +11,7 @@ import dev.brighten.ac.api.event.result.PunishResult; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.utils.*; import dev.brighten.ac.utils.timer.Timer; -import dev.brighten.ac.utils.timer.impl.MillisTimer; +import dev.brighten.ac.utils.timer.impl.TickTimer; import lombok.Getter; import lombok.Setter; import lombok.val; @@ -21,6 +21,7 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public class Check implements ECheck { @@ -37,7 +38,8 @@ public class Check implements ECheck { @Getter @Setter private int punishVl; - private final Timer lastAlert = new MillisTimer(); + private static final Timer alertCountReset = new TickTimer(); + private static final AtomicInteger alertCount = new AtomicInteger(0); public static Set alertsEnabled = new HashSet<>(); @@ -96,7 +98,8 @@ public class Check implements ECheck { } else { player.getInfo().getLastCancel().reset(); - Location ground = player.getInfo().isServerGround() ? player.getMovement().getFrom().getLoc() + Location ground = player.getInfo().isServerGround() && player.getMovement().getLastTeleport().isPassed(1) + ? player.getMovement().getFrom().getLoc() .toLocation(player.getBukkitPlayer().getWorld()) : MovementUtils.findGroundLocation(player.getMovement().getFrom().getLoc() .toLocation(player.getBukkitPlayer().getWorld()), 10); @@ -176,7 +179,12 @@ public class Check implements ECheck { .execute(() -> Anticheat.INSTANCE.getLogManager() .insertLog(player, checkData, vl, System.currentTimeMillis(), info)); - if(lastAlert.isPassed(200L)) { + if(alertCountReset.isPassed(20)) { + alertCount.set(0); + alertCountReset.reset(); + } + + if(alertCount.incrementAndGet() < 30) { boolean dev = Anticheat.INSTANCE.getTps() < 18; //if(vl > 0) Anticheat.INSTANCE.loggerManager.addLog(player, this, info); @@ -206,7 +214,7 @@ public class Check implements ECheck { .ifPresent(apl -> apl.getBukkitPlayer().spigot().sendMessage(toSend .toArray(new BaseComponent[0]))); } - lastAlert.reset(); + alertCountReset.reset(); } if(punish && vl >= punishVl) { punish(); diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java b/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java new file mode 100644 index 0000000..bcc2205 --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KABot.java @@ -0,0 +1,29 @@ +package dev.brighten.ac.check.impl.combat.killaura; + +import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity; +import lombok.val; + +@CheckData(name = "KillAura (Bot)", checkId = "kabot", type = CheckType.KILLAURA) +public class KABot extends Check { + + public KABot(APlayer player) { + super(player); + } + + private int buffer = 0; + + WAction packet = packet -> { + val optional = player.getEntityLocationHandler().getFakeMob(packet.getEntityId()); + + if(optional.isPresent()) { + if(++buffer > 1) { + flag("Attacked player without attacking bot!"); + } + } else buffer = 0; + }; +} diff --git a/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java b/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java new file mode 100644 index 0000000..8031567 --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/impl/combat/killaura/KATrace.java @@ -0,0 +1,87 @@ +package dev.brighten.ac.check.impl.combat.killaura; + +import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.ProtocolVersion; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInUseEntity; +import dev.brighten.ac.utils.KLocation; +import dev.brighten.ac.utils.MathUtils; +import dev.brighten.ac.utils.world.CollisionBox; +import dev.brighten.ac.utils.world.EntityData; +import dev.brighten.ac.utils.world.types.RayCollision; +import dev.brighten.ac.utils.world.types.SimpleCollisionBox; +import org.bukkit.util.Vector; + +@CheckData(name = "KillAura (Trace)", checkId = "katrace", type = CheckType.KILLAURA) +public class KATrace extends Check { + + private float sneakY = 1.54f; + public KATrace(APlayer player) { + super(player); + + sneakY = player.getPlayerVersion().isBelow(ProtocolVersion.V1_14) ? 1.27f : 1.54f; + } + + private int buffer; + + WAction useEntity = packet -> { + if(player.getInfo().getTarget() == null + || packet.getAction() != WPacketPlayInUseEntity.EnumEntityUseAction.ATTACK) + return; + + if(player.getMovement().getLookingAtBoxes().size() == 0) { + debug("No boxes to look at!"); + buffer = 0; + return; + } + + SimpleCollisionBox targetBox = (SimpleCollisionBox) EntityData.getEntityBox(player.getInfo().getTarget().getLocation(), + player.getInfo().target); + + if(targetBox == null) return; + + KLocation origin = player.getMovement().getTo().getLoc().clone(); + + origin.y+= player.getInfo().isSneaking() ? sneakY : 1.62f; + + RayCollision collision = new RayCollision(origin.toVector(), MathUtils.getDirection(origin)); + + Vector targetPoint = collision.collisionPoint(targetBox); + //If the ray isn't collided, we might as well not run this check. Just a simple boxes on array check + if(targetPoint == null) return; + + double dist = origin.toVector().distanceSquared(targetPoint); + + boolean rayCollidedOnBlock = false; + + synchronized (player.getMovement().getLookingAtBoxes()) { + for (CollisionBox lookingAtBox : player.getMovement().getLookingAtBoxes()) { + if((lookingAtBox instanceof SimpleCollisionBox)) { + SimpleCollisionBox box = (SimpleCollisionBox) lookingAtBox; + if(box.xMin % 1 != 0 || box.yMin % 1 != 0 || box.zMin % 1 != 0 + || box.xMax % 1 != 0 || box.yMax % 1 != 0 || box.zMax % 1 != 0) + continue; + + Vector point = collision.collisionPoint(box.copy().shrink(0.005f, 0.005f, 0.005f)); + + if (point != null && origin.toVector().distanceSquared(point) < dist - 0.2) { + rayCollidedOnBlock = true; + break; + } + } + } + } + + if(rayCollidedOnBlock) { + if(++buffer > 2) { + flag("Attacker hit through block! [b=%s s=%s]", + buffer, player.getMovement().getLookingAtBoxes().size()); + } + } else if(buffer > 0) buffer--; + + debug("b=%s collides=%s", buffer, rayCollidedOnBlock); + }; +} diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java index 6ed130c..c7e4b69 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyA.java @@ -1,15 +1,15 @@ package dev.brighten.ac.check.impl.movement.fly; -import dev.brighten.ac.check.WAction; +import dev.brighten.ac.api.check.CheckType; import dev.brighten.ac.check.Check; import dev.brighten.ac.check.CheckData; -import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.WAction; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.packet.ProtocolVersion; import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; -import dev.brighten.ac.utils.annotation.Async; import dev.brighten.ac.utils.MathUtils; import dev.brighten.ac.utils.MovementUtils; +import dev.brighten.ac.utils.annotation.Async; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; @@ -41,10 +41,6 @@ public class FlyA extends Check { predicted = MovementUtils.getJumpHeight(player); } - if(Math.abs(predicted) < 0.005 && ProtocolVersion.getGameVersion().isOrAbove(ProtocolVersion.V1_9)) { - predicted = 0; - } - // There will be missed movements that we can't account for if we had to predict the player's next position // twice, so we shouldn't flag regardless. boolean willBeWeirdNext = didNextPrediction; @@ -61,6 +57,13 @@ public class FlyA extends Check { } } + if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) { + if(Math.abs(predicted) < 0.005) + predicted = 0; + } else if(Math.abs(predicted) < 0.003) { + predicted = 0; + } + double deltaPredict = MathUtils.getDelta(player.getMovement().getDeltaY(), predicted); if(!player.getInfo().isGeneralCancel() @@ -77,7 +80,8 @@ public class FlyA extends Check { && !player.getInfo().isServerGround() && !player.getBlockInfo().onHalfBlock && player.getInfo().getVelocity().isPassed(1) - && !player.getBlockInfo().onSlime && deltaPredict > 0.001) { + && !player.getBlockInfo().onSlime + && deltaPredict > (player.getInfo().getClientAirTicks() < 3 ? 0.017 : 0.001)) { if(++buffer > 3) { buffer = 3; flag("dY=%.3f p=%.3f dx=%.3f", player.getMovement().getDeltaY(), predicted, diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java index e95c022..e8cb0fd 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyB.java @@ -21,13 +21,15 @@ public class FlyB extends Check { @Async WAction flying = packet -> { - if(player.getInfo().isNearGround()) lastNearGround.reset(); + if((player.getInfo().isNearGround() && !player.getBlockInfo().collidesHorizontally) + || player.getInfo().isServerGround()) lastNearGround.reset(); if(!packet.isMoved() || player.getInfo().isGeneralCancel()) return; if(player.getMovement().getDeltaY() - player.getMovement().getLDeltaY() > 0.01 - && player.getMovement().getMoveTicks() > 3 + && player.getMovement().getMoveTicks() > 1 && player.getInfo().getLastPlace().isPassed(3) && lastNearGround.isPassed(2) + && !player.getInfo().onLadder && player.getInfo().lastLiquid.isPassed(1) && player.getInfo().climbTimer.isPassed(1) && player.getInfo().getVelocity().isPassed(2) diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyE.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyE.java new file mode 100644 index 0000000..918e788 --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyE.java @@ -0,0 +1,42 @@ +package dev.brighten.ac.check.impl.movement.fly; + +import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; + +@CheckData(name = "Fly (E)", checkId = "flye", type = CheckType.MOVEMENT) +public class FlyE extends Check { + + public FlyE(APlayer player) { + super(player); + } + + private int buffer; + + WAction flying = packet -> { + if(player.getInfo().getVelocity().isNotPassed(20) + || player.getMovement().getMoveTicks() == 0 + || player.getInfo().isCreative() + || player.getBlockInfo().blocksAbove + || player.getMovement().getTeleportsToConfirm() > 0 + || player.getInfo().isCanFly() + || player.getInfo().getLastElytra().isNotPassed(5)) + return; + + final double deltaY = player.getMovement().getDeltaY(), + lDeltaY = player.getMovement().getLDeltaY(); + + if(Math.abs(deltaY + lDeltaY) < 0.05 && player.getInfo().lastHalfBlock.isPassed(2) + && player.getInfo().slimeTimer.isPassed(5) + && Math.abs(deltaY) > 0.2) { + buffer+= 15; + if(buffer > 20) { + flag("dy=%s ly=%s", deltaY, lDeltaY); + buffer= 20; // Prevents flagging too much + } + } else if(buffer > 0) buffer--; + }; +} diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyF.java b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyF.java new file mode 100644 index 0000000..66d2db9 --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/impl/movement/fly/FlyF.java @@ -0,0 +1,30 @@ +package dev.brighten.ac.check.impl.movement.fly; + +import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying; + +@CheckData(name = "Fly (F)", checkId = "flyf", type = CheckType.MOVEMENT) +public class FlyF extends Check { + public FlyF(APlayer player) { + super(player); + } + + WAction flying = packet -> { + if(!packet.isMoved() + || player.getInfo().blockAbove.isNotPassed(4) + || player.getInfo().climbTimer.isNotPassed(2) + || packet.isOnGround() + || player.getMovement().getMoveTicks() < 3 + || player.getInfo().isGeneralCancel()) return; + + double acceleration = player.getMovement().getDeltaY() - player.getMovement().getLDeltaY(); + + if(acceleration < (player.getMovement().getDeltaXZ() < 0.1 ? -0.17 : -0.1)) { + flag("acceleration=%.4f", acceleration); + } + }; +} diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java index 2a6589d..611050a 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/nofall/NoFallA.java @@ -36,6 +36,7 @@ public class NoFallA extends Check { && player.getInfo().slimeTimer.isPassed(2) && player.getInfo().getBlockAbove().isPassed(3) && !player.getInfo().isServerGround() + && !player.getBlockInfo().fenceNear && (player.getMovement().getDeltaY() >= 0 && (Math.abs(player.getMovement().getTo().getLoc().y) % divisor != 0 || Math.abs(player.getMovement().getDeltaY()) % divisor != 0) diff --git a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java index f6e7544..945cbaf 100644 --- a/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java +++ b/src/main/java/dev/brighten/ac/check/impl/movement/speed/Horizontal.java @@ -41,6 +41,7 @@ public class Horizontal extends Check { if (!packet.isMoved() || player.getMovement().getMoveTicks() == 0 + || player.getMovement().getLastTeleport().isNotPassed(1) || player.getInfo().getVelocity().isNotPassed(2) || player.getInfo().isGeneralCancel() || player.getBlockInfo().onClimbable @@ -54,10 +55,10 @@ public class Horizontal extends Check { Deque frictionList = player.getBlockUpdateHandler() .getPossibleMaterials(new IntVector(MathHelper.floor_double(underBlockLoc.x), - MathHelper.floor_double(underBlockLoc.y), MathHelper.floor_double(underBlockLoc.z))), + MathHelper.floor_double(underBlockLoc.y - 1), MathHelper.floor_double(underBlockLoc.z))), lfrictionList = player.getBlockUpdateHandler() .getPossibleMaterials(new IntVector(MathHelper.floor_double(lastUnderBlockLoc.x), - MathHelper.floor_double(lastUnderBlockLoc.y), + MathHelper.floor_double(lastUnderBlockLoc.y - 1), MathHelper.floor_double(lastUnderBlockLoc.z))); double smallestDelta = Double.MAX_VALUE; @@ -123,6 +124,16 @@ public class Horizontal extends Check { } } + /*if(!sneaking && player.getBlockInfo().onSlime + && player.getBlockInfo().collisionMaterialCount + .containsKey(Material.SLIME_BLOCK)) { + for(int i = 0 ; i < player.getBlockInfo() + .collisionMaterialCount + .get(Material.SLIME_BLOCK) ; i++) { + lmotionX*= + } + }*/ + if(player.getBlockInfo().inWeb) { lmotionX*= 0.25; lmotionZ*= 0.25; @@ -281,7 +292,7 @@ public class Horizontal extends Check { } private static boolean[] getSneakingIteration(boolean sprinting) { - return sprinting ? new boolean[] {false} : new boolean[] {true, false}; + return new boolean[] {true, false}; } private static boolean[] getJumpingIteration(boolean sprinting) { diff --git a/src/main/java/dev/brighten/ac/check/impl/packet/Metadata.java b/src/main/java/dev/brighten/ac/check/impl/packet/Metadata.java new file mode 100644 index 0000000..f9f659e --- /dev/null +++ b/src/main/java/dev/brighten/ac/check/impl/packet/Metadata.java @@ -0,0 +1,39 @@ +package dev.brighten.ac.check.impl.packet; + +import dev.brighten.ac.api.check.CheckType; +import dev.brighten.ac.check.Check; +import dev.brighten.ac.check.CheckData; +import dev.brighten.ac.check.WAction; +import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityMetadata; +import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutSpawnEntityLiving; + +@CheckData(name = "Metadata", checkId = "metadata", type = CheckType.BADPACKETS) +public class Metadata extends Check { + + public Metadata(APlayer player) { + super(player); + } + + WAction packet = packet -> { + debug("entityId: " + packet.getEntityId()); + packet.getWatchedObjects().forEach(watchedObject -> { + debug("watchedObject: " + watchedObject.getObjectType() + "," + watchedObject.getDataValueId() + ", " + watchedObject.getWatchedObject()); + }); + }; + + WAction spawn = packet -> { + debug("(spawned) entityId: " + packet.getEntityId()); + packet.getWatchedObjects().forEach(watchedObject -> { + if(watchedObject.getDataValueId() == 0) { + byte bitInfo = (byte) watchedObject.getWatchedObject(); + boolean sneaking = (bitInfo & 1 << 1) != 0; + boolean sprinting = (bitInfo & 1 << 3) != 0; + boolean invisible = (bitInfo & 1 << 5) != 0; + + debug("sneaking:%s sprinting:%s invisible:%s", sneaking, sprinting, invisible); + } + debug("watchedObject: " + watchedObject.getObjectType() + "," + watchedObject.getDataValueId() + ", " + watchedObject.getWatchedObject()); + }); + }; +} diff --git a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java index 47ae565..2607e0a 100644 --- a/src/main/java/dev/brighten/ac/command/AnticheatCommand.java +++ b/src/main/java/dev/brighten/ac/command/AnticheatCommand.java @@ -32,6 +32,7 @@ import net.minecraft.server.v1_8_R3.PacketPlayOutTitle; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.v1_8_R3.util.CraftChatMessage; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.plugin.InvalidDescriptionException; import org.bukkit.plugin.Plugin; @@ -211,13 +212,12 @@ public class AnticheatCommand extends BaseCommand { @Subcommand("spawnbot") @CommandPermission("anticheat.command.spawnbot") @Description("Spawn test bot") - public void onBot(Player player) { - FakeMob fakePlayer = new FakeMob(player.getLocation().getWorld()); + public void onBot(APlayer player) { + FakeMob fakePlayer = new FakeMob(EntityType.ZOMBIE); - fakePlayer.spawn(player.getLocation(), Anticheat.INSTANCE.getPlayerRegistry() - .getPlayer(player.getUniqueId()).orElseThrow(() -> new RuntimeException("shit"))); + fakePlayer.spawn(true, player.getBukkitPlayer().getLocation(), player); - player.sendMessage(Color.Green + "Spawned entity with ID: " + fakePlayer.getEntityId()); + player.getBukkitPlayer().sendMessage(Color.Green + "Spawned entity with ID: " + fakePlayer.getEntityId()); } @Subcommand("botinvis") diff --git a/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java b/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java index 70b3f82..c7b4509 100644 --- a/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java +++ b/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java @@ -2,22 +2,21 @@ package dev.brighten.ac.handler; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.packet.ProtocolVersion; -import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntity; -import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityTeleport; +import dev.brighten.ac.packet.wrapper.out.*; import dev.brighten.ac.utils.EntityLocation; import dev.brighten.ac.utils.Tuple; import dev.brighten.ac.utils.timer.Timer; import dev.brighten.ac.utils.timer.impl.MillisTimer; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import lombok.RequiredArgsConstructor; import lombok.val; +import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import java.util.EnumSet; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; @RequiredArgsConstructor @@ -26,7 +25,11 @@ public class EntityLocationHandler { private final APlayer data; private final Map> entityLocationMap = new ConcurrentHashMap<>(); + private final Map fakeMobs = new Int2ObjectArrayMap<>(); + private final Map fakeMobToEntityId = new Int2ObjectArrayMap<>(); private final Timer lastFlying = new MillisTimer(); + + public Set canCreateMob = new HashSet<>(); public int streak; private static final EnumSet allowedEntityTypes = EnumSet.of(EntityType.ZOMBIE, EntityType.SHEEP, @@ -45,6 +48,14 @@ public class EntityLocationHandler { return Optional.ofNullable(entityLocationMap.get(entity.getUniqueId())); } + public Optional getFakeMob(int entityId) { + return Optional.ofNullable(fakeMobs.get(entityId)); + } + + public Optional getTargetOfFakeMob(int fakeMobId) { + return Optional.ofNullable(fakeMobToEntityId.get(fakeMobId)); + } + /** * * We are processing PacketPlayInFlying to iterate the tracked entity locations @@ -90,7 +101,12 @@ public class EntityLocationHandler { if(!allowedEntityTypes.contains(entity.getType())) return; val tuple = entityLocationMap.computeIfAbsent(entity.getUniqueId(), - key -> new Tuple<>(new EntityLocation(entity), null)); + key -> { + createFakeMob(packet.getId(), entity.getLocation()); + return new Tuple<>(new EntityLocation(entity), null); + }); + + processFakeMobs(packet.getId(), true, packet.getX(), packet.getY(), packet.getZ()); EntityLocation eloc = tuple.one; @@ -123,8 +139,14 @@ public class EntityLocationHandler { if(!allowedEntityTypes.contains(entity.getType())) return; + val tuple = entityLocationMap.computeIfAbsent(entity.getUniqueId(), - key -> new Tuple<>(new EntityLocation(entity), null)); + key -> { + createFakeMob(packet.getEntityId(), entity.getLocation()); + return new Tuple<>(new EntityLocation(entity), null); + }); + + processFakeMobs(packet.getEntityId(), false, packet.getX(), packet.getY(), packet.getZ()); EntityLocation eloc = tuple.one; @@ -188,4 +210,64 @@ public class EntityLocationHandler { entityLocationMap.get(entity.getUniqueId()).two = null, 1); } } + + public void onSpawnEntity(WPacketPlayOutNamedEntitySpawn packet) { + createFakeMob(packet.getEntityId(), new Location(data.getBukkitPlayer().getWorld(), packet.getX(), packet.getY(), packet.getZ())); + } + + public void onSpawnEntity(WPacketPlayOutSpawnEntityLiving packet) { + if(!allowedEntityTypes.contains(packet.getType())) return; + + createFakeMob(packet.getEntityId(), new Location(data.getBukkitPlayer().getWorld(), packet.getX(), packet.getY(), packet.getZ())); + } + + public void onEntityDestroy(WPacketPlayOutEntityDestroy packet) { + for(int id : packet.getEntityIds()) { + if(fakeMobs.containsKey(id)) { + FakeMob mob = fakeMobs.get(id); + mob.despawn(); + fakeMobToEntityId.remove(mob.getEntityId()); + fakeMobs.remove(id); + } + } + } + + public void removeFakeMob(int id) { + if(fakeMobs.containsKey(id)) { + FakeMob mob = fakeMobs.get(id); + mob.despawn(); + fakeMobToEntityId.remove(mob.getEntityId()); + fakeMobs.remove(id); + } + } + + private void createFakeMob(int entityId, Location location) { + if(!canCreateMob.contains(entityId)) return; + FakeMob mob = new FakeMob(EntityType.GIANT); + + mob.spawn(true, location, data); + + this.fakeMobs.put(entityId, mob); + fakeMobToEntityId.put(mob.getEntityId(), entityId); + canCreateMob.remove(entityId); + } + + public void processFakeMobs(int entityId, boolean rel, double x, double y, double z) { + FakeMob fakeMob = fakeMobs.get(entityId); + + if(fakeMob == null) { + if(!rel) { + createFakeMob(entityId, new Location(data.getBukkitPlayer().getWorld(), x, y, z)); + fakeMob = fakeMobs.get(entityId); + + if(fakeMob == null) return; + } else return; + } + + if(rel) { + fakeMob.move(x, y, z); + } else { + fakeMob.teleport(x, y, z, 0, 0); + } + } } diff --git a/src/main/java/dev/brighten/ac/handler/MovementHandler.java b/src/main/java/dev/brighten/ac/handler/MovementHandler.java index 0e817cb..414cfaa 100644 --- a/src/main/java/dev/brighten/ac/handler/MovementHandler.java +++ b/src/main/java/dev/brighten/ac/handler/MovementHandler.java @@ -10,6 +10,8 @@ import dev.brighten.ac.utils.*; 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 lombok.Getter; import lombok.RequiredArgsConstructor; @@ -39,7 +41,9 @@ public class MovementHandler { private int moveTicks; private final List posLocs = new ArrayList<>(); @Getter - private boolean checkMovement, accurateYawData, cinematic, jumped, inAir; + private final List lookingAtBoxes = new ArrayList<>(); + @Getter + private boolean checkMovement, accurateYawData, cinematic, jumped, inAir, lookingAtBlock; @Getter @Setter private boolean excuseNextFlying; @@ -141,7 +145,18 @@ public class MovementHandler { val origin = this.to.getLoc().clone(); - origin.y += player.getInfo().isSneaking() ? 1.54 : 1.62; + origin.y += player.getInfo().isSneaking() + ? (player.getPlayerVersion().isBelow(ProtocolVersion.V1_14) ? 1.54 : 1.27f) : 1.62; + + RayCollision collision = new RayCollision(origin.toVector(), MathUtils.getDirection(origin)); + + synchronized (lookingAtBoxes) { + lookingAtBoxes.clear(); + lookingAtBoxes.addAll(collision + .boxesOnRay(player.getBukkitPlayer().getWorld(), + player.getBukkitPlayer().getGameMode().equals(GameMode.CREATIVE) ? 6.0 : 5.0)); + lookingAtBlock = lookingAtBoxes.size() > 0; + } if (lastTeleport.isPassed(1)) { predictionHandling: diff --git a/src/main/java/dev/brighten/ac/handler/PacketHandler.java b/src/main/java/dev/brighten/ac/handler/PacketHandler.java index eee79b0..febabb0 100644 --- a/src/main/java/dev/brighten/ac/handler/PacketHandler.java +++ b/src/main/java/dev/brighten/ac/handler/PacketHandler.java @@ -3,6 +3,7 @@ package dev.brighten.ac.handler; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.data.obj.NormalAction; +import dev.brighten.ac.handler.entity.FakeMob; import dev.brighten.ac.packet.ProtocolVersion; import dev.brighten.ac.packet.wrapper.PacketType; import dev.brighten.ac.packet.wrapper.in.*; @@ -228,6 +229,12 @@ public class PacketHandler { } break; } + case ENTITY_DESTROY: { + WPacketPlayOutEntityDestroy packet = (WPacketPlayOutEntityDestroy) packetObject; + + player.getEntityLocationHandler().onEntityDestroy(packet); + break; + } case ENTITY_ACTION: { WPacketPlayInEntityAction packet = (WPacketPlayInEntityAction) packetObject; @@ -269,10 +276,22 @@ public class PacketHandler { case USE_ENTITY: { WPacketPlayInUseEntity packet = (WPacketPlayInUseEntity) packetObject; - Entity target = packet.getEntity(player.getBukkitPlayer().getWorld()); + FakeMob mob = Anticheat.INSTANCE.getFakeTracker().getEntityById(packet.getEntityId()); - if(target instanceof LivingEntity) { - player.getInfo().setTarget((LivingEntity) target); + if(mob != null) { + player.getEntityLocationHandler().getTargetOfFakeMob(mob.getEntityId()) + .ifPresent(targetId -> { + player.getEntityLocationHandler().removeFakeMob(targetId); + }); + } else { + Entity target = packet.getEntity(player.getBukkitPlayer().getWorld()); + + if(target instanceof LivingEntity) { + if(Math.random() > 0.9) { + player.getEntityLocationHandler().canCreateMob.add(target.getEntityId()); + } + player.getInfo().setTarget((LivingEntity) target); + } } break; } diff --git a/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java b/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java index b304709..10a535d 100644 --- a/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java +++ b/src/main/java/dev/brighten/ac/handler/block/BlockUpdateHandler.java @@ -164,6 +164,13 @@ public class BlockUpdateHandler { blockI.add(type); + blockInformation.put(loc, blockI); + } else if(blockI.size() == 0) { + Material type = Wrapper.getInstance().getType(player.getBukkitPlayer().getWorld(), + loc.getX(), loc.getY(), loc.getZ()); + + blockI.add(type); + blockInformation.put(loc, blockI); } diff --git a/src/main/java/dev/brighten/ac/handler/entity/FakeEntityTracker.java b/src/main/java/dev/brighten/ac/handler/entity/FakeEntityTracker.java index 480cbaa..0b7208d 100644 --- a/src/main/java/dev/brighten/ac/handler/entity/FakeEntityTracker.java +++ b/src/main/java/dev/brighten/ac/handler/entity/FakeEntityTracker.java @@ -22,7 +22,7 @@ public class FakeEntityTracker { } public void despawnAll() { - entityMap.forEach((id, entity) -> entity.despawn()); + entityMap.values().forEach(FakeMob::despawn); entityMap.clear(); } } diff --git a/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java b/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java index 72270b4..2808eb1 100644 --- a/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java +++ b/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java @@ -2,19 +2,15 @@ package dev.brighten.ac.handler.entity; import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; +import dev.brighten.ac.packet.wrapper.objects.WrappedWatchableObject; import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntity; -import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityEffect; +import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityMetadata; import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutEntityTeleport; -import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutRemoveEntityEffect; +import dev.brighten.ac.packet.wrapper.out.WPacketPlayOutSpawnEntityLiving; import lombok.Getter; -import net.minecraft.server.v1_8_R3.EntityZombie; import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; -import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; import org.bukkit.entity.EntityType; -import org.bukkit.potion.PotionEffectType; import java.util.ArrayList; import java.util.Collections; @@ -25,32 +21,52 @@ import java.util.concurrent.ThreadLocalRandom; public class FakeMob { private int entityId; private EntityType type; - private EntityZombie zombie; private List watching = Collections.emptyList(); - public FakeMob(World world) { + public FakeMob(EntityType type) { entityId = ThreadLocalRandom.current().nextInt(15000, 20000); - - zombie = new EntityZombie(((CraftWorld)world).getHandle()); - entityId = zombie.getId(); + this.type = type; } - public void spawn(Location location, APlayer... players) { + /* + protected void b(int i, boolean flag) { + byte b0 = this.datawatcher.getByte(0); + if (flag) { + this.datawatcher.watch(0, (byte)(b0 | 1 << i)); + } else { + this.datawatcher.watch(0, (byte)(b0 & ~(1 << i))); + } + + } + */ + public void spawn(boolean invisible, Location location, APlayer... players) { if(watching.size() > 0) { despawn(); } - zombie = new EntityZombie(((CraftWorld)location.getWorld()).getHandle()); - zombie.setInvisible(true); - zombie.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - zombie.setHealth(20f); - - entityId = zombie.getId(); watching = new ArrayList<>(); for (APlayer player : players) { - PacketPlayOutSpawnEntityLiving living = new PacketPlayOutSpawnEntityLiving(zombie); - player.sendPacket(living); + List objects = new ArrayList<>(); + if(invisible) { + objects.add(new WrappedWatchableObject(0, 0, (byte)((byte)1 << 5))); + } + WPacketPlayOutSpawnEntityLiving packet = WPacketPlayOutSpawnEntityLiving.builder() + .entityId(entityId) + .type(type) + .x(location.getX()) + .y(location.getY()) + .z(location.getZ()) + .yaw(location.getYaw()) + .pitch(location.getPitch()) + .headYaw(location.getYaw()) + .motionX(0) + .motionY(0) + .motionZ(0) + .watchedObjects(objects) + .build(); + + player.sendPacket(packet); watching.add(player); } @@ -58,23 +74,20 @@ public class FakeMob { } public void setInvisible(boolean invisible) { + List objects = new ArrayList<>(); + if(invisible) { - WPacketPlayOutEntityEffect packet = WPacketPlayOutEntityEffect.builder().entityId(entityId) - .effectId(PotionEffectType.INVISIBILITY.getId() & 255).amplifier((byte)0).duration(32767).flags((byte)0x02).build(); - - for (APlayer player : watching) { - player.sendPacket(packet); - } - zombie.setInvisible(true); + objects.add(new WrappedWatchableObject(0, 0, (byte)((byte)1 << 5))); } else { - WPacketPlayOutRemoveEntityEffect packet = WPacketPlayOutRemoveEntityEffect.builder() - .effect(PotionEffectType.INVISIBILITY).entityId(entityId).build(); - - for (APlayer player : watching) { - player.sendPacket(packet); - } - zombie.setInvisible(false); + objects.add(new WrappedWatchableObject(0, 0, (byte)~((byte)1 << 5))); } + + WPacketPlayOutEntityMetadata packet = WPacketPlayOutEntityMetadata.builder() + .entityId(entityId) + .watchedObjects(objects) + .build(); + + watching.forEach(player -> player.sendPacket(packet)); } public void despawn() { @@ -84,13 +97,12 @@ public class FakeMob { aPlayer.sendPacket(destroyEntity); } watching = Collections.emptyList(); - zombie = null; Anticheat.INSTANCE.getFakeTracker().untrackEntity(this); } public void move(double dx, double dy, double dz) { - WPacketPlayOutEntity packet = WPacketPlayOutEntity.builder().x(dx).y(dy).z(dz).moved(true).build(); + WPacketPlayOutEntity packet = WPacketPlayOutEntity.builder().id(entityId).x(dx).y(dy).z(dz).moved(true).build(); for (APlayer player : watching) { player.sendPacket(packet); @@ -98,7 +110,7 @@ public class FakeMob { } public void move(double dx, double dy, double dz, float dyaw, float dpitch) { - WPacketPlayOutEntity packet = WPacketPlayOutEntity.builder().x(dx).y(dy).z(dz).yaw(dyaw) + WPacketPlayOutEntity packet = WPacketPlayOutEntity.builder().id(entityId).x(dx).y(dy).z(dz).yaw(dyaw) .pitch(dpitch).moved(true).looked(true).build(); for (APlayer player : watching) { @@ -107,7 +119,7 @@ public class FakeMob { } public void move(float dyaw, float dpitch) { - WPacketPlayOutEntity packet = WPacketPlayOutEntity.builder().yaw(dyaw).pitch(dpitch) + WPacketPlayOutEntity packet = WPacketPlayOutEntity.builder().id(entityId).yaw(dyaw).pitch(dpitch) .looked(true).build(); for (APlayer player : watching) { diff --git a/src/main/java/dev/brighten/ac/handler/entity/hit/HitEntityTracker.java b/src/main/java/dev/brighten/ac/handler/entity/hit/HitEntityTracker.java deleted file mode 100644 index dd8dfc0..0000000 --- a/src/main/java/dev/brighten/ac/handler/entity/hit/HitEntityTracker.java +++ /dev/null @@ -1,4 +0,0 @@ -package dev.brighten.ac.handler.entity.hit; - -public class HitEntityTracker { -} diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java b/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java index 6f9929b..8c7d8a3 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/PacketConverter.java @@ -75,4 +75,6 @@ public interface PacketConverter { WPacketPlayOutEntityMetadata processEntityMetadata(Object object); Object processEntityMetadata(WPacketPlayOutEntityMetadata packet); + + WPacketPlayOutEntityDestroy processEntityDestroy(Object object); } diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java b/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java index 95d6eb5..f36de55 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/PacketType.java @@ -140,6 +140,10 @@ public enum PacketType { return convert.processSpawnLiving(object); case REMOVE_EFFECT: return convert.processRemoveEffect(object); + case ENTITY_METADATA: + return convert.processEntityMetadata(object); + case ENTITY_DESTROY: + return convert.processEntityDestroy(object); default: return object; } diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java b/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java index ff01c91..aa6fd86 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/impl/Processor_18.java @@ -14,6 +14,8 @@ import dev.brighten.ac.utils.math.IntVector; import dev.brighten.ac.utils.reflections.types.WrappedClass; import dev.brighten.ac.utils.reflections.types.WrappedField; import io.netty.buffer.Unpooled; +import lombok.SneakyThrows; +import lombok.val; import net.minecraft.server.v1_8_R3.*; import org.bukkit.Material; import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; @@ -23,8 +25,7 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; import java.io.IOException; -import java.util.Arrays; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; public class Processor_18 implements PacketConverter { @@ -391,7 +392,7 @@ public class Processor_18 implements PacketConverter { serial.writeBoolean(packet.isOnGround()); try { - vanilla.b(serial); + vanilla.a(serial); } catch (IOException e) { throw new RuntimeException(e); } @@ -626,24 +627,33 @@ public class Processor_18 implements PacketConverter { return vanilla; } + private static WrappedClass classSpawnEntityLiving = new WrappedClass(PacketPlayOutSpawnEntityLiving.class); + private static WrappedField splDataWatcher = classSpawnEntityLiving.getFieldByType(DataWatcher.class, 0), + splWatchList = classSpawnEntityLiving.getFieldByType(List.class, 0); + + @SneakyThrows @Override public WPacketPlayOutSpawnEntityLiving processSpawnLiving(Object object) { PacketPlayOutSpawnEntityLiving packet = (PacketPlayOutSpawnEntityLiving) object; PacketDataSerializer s = serialize(packet); - WPacketPlayOutSpawnEntityLiving sel = WPacketPlayOutSpawnEntityLiving.builder().entityId(s.e()) + val builder = WPacketPlayOutSpawnEntityLiving.builder().entityId(s.e()) .type(EntityType.fromId(s.readByte() & 255)).x(s.readInt() / 32.).y(s.readInt() / 32.) .z(s.readInt()/ 32.).yaw(s.readByte() * 360.F / 256.F).pitch(s.readByte() * 360.F / 256.F) .headYaw(s.readByte() * 360.F / 256.F).motionX(s.readShort() / 8000.).motionY(s.readShort() / 8000.) - .motionZ(s.readShort() / 8000.).build(); + .motionZ(s.readShort() / 8000.); + val watchedObjects = DataWatcher.b(s); + if(watchedObjects != null) { + builder.watchedObjects(watchedObjects.stream().map(WrappedWatchableObject::new).collect(Collectors.toList())); + } else builder.watchedObjects(new ArrayList<>()); - return sel; + return builder.build(); } - private static WrappedClass classSpawnEntityLiving = new WrappedClass(PacketPlayOutSpawnEntityLiving.class); - private static WrappedField splDataWatcher = classSpawnEntityLiving.getFieldByType(DataWatcher.class, 0); + private static WrappedClass dataWatcherClass = new WrappedClass(DataWatcher.class); + private static WrappedField watchableMap = dataWatcherClass.getFieldByName("d"); @Override public Object processSpawnLiving(WPacketPlayOutSpawnEntityLiving packet) { PacketPlayOutSpawnEntityLiving vanilla = new PacketPlayOutSpawnEntityLiving(); @@ -663,8 +673,14 @@ public class Processor_18 implements PacketConverter { try { DataWatcher watcher = new DataWatcher(null); - splDataWatcher.set(vanilla, watcher); + + packet.getWatchedObjects().forEach(w ->{ + watcher.a(w.getDataValueId(), w.getWatchedObject()); + System.out.println("Adding object: " + w.getDataValueId() + ";" + w.getWatchedObject()); + }); + watcher.a(serializer); + splDataWatcher.set(vanilla, watcher); vanilla.a(serializer); } catch (IOException e) { throw new RuntimeException(e); @@ -747,6 +763,21 @@ public class Processor_18 implements PacketConverter { return vanilla; } + @Override + public WPacketPlayOutEntityDestroy processEntityDestroy(Object object) { + PacketPlayOutEntityDestroy packet = (PacketPlayOutEntityDestroy) object; + + PacketDataSerializer serialized = serialize(packet); + + int[] entityIds = new int[serialized.e()]; + + for(int var2 = 0; var2 < entityIds.length; ++var2) { + entityIds[var2] = serialized.e(); + } + + return WPacketPlayOutEntityDestroy.builder().entityIds(entityIds).build(); + } + private PacketDataSerializer serialize(Packet packet) { PacketDataSerializer serial = new PacketDataSerializer(Unpooled.buffer()); try { @@ -756,4 +787,54 @@ public class Processor_18 implements PacketConverter { } return serial; } + + private static void writePacketData(PacketDataSerializer serializer, List objects) { + for (WrappedWatchableObject object : objects) { + System.out.println("Writing object:" + object.getDataValueId() + ";" + object.getWatchedObject()); + int i = (object.getObjectType() << 5 | object.getDataValueId() & 31) & 255; + serializer.writeByte(i); + switch (object.getObjectType()) { + case 0: { + serializer.writeByte((Byte)object.getWatchedObject()); + break; + } + case 1: { + serializer.writeShort((Short)object.getWatchedObject()); + break; + } + case 2: { + serializer.writeInt((Integer)object.getWatchedObject()); + break; + } + case 3: { + serializer.writeFloat((Float)object.getWatchedObject()); + break; + } + case 4: { + serializer.a((String)object.getWatchedObject()); + break; + } + case 5: { + ItemStack itemStack = (ItemStack)object.getWatchedObject(); + serializer.a(itemStack); + break; + } + case 6: { + BlockPosition blockPosition = (BlockPosition)object.getWatchedObject(); + serializer.writeInt(blockPosition.getX()); + serializer.writeInt(blockPosition.getY()); + serializer.writeInt(blockPosition.getZ()); + break; + } + case 7: { + Vector3f vector3f = (Vector3f)object.getWatchedObject(); + serializer.writeFloat(vector3f.getX()); + serializer.writeFloat(vector3f.getY()); + serializer.writeFloat(vector3f.getZ()); + break; + } + } + } + serializer.writeByte(127); + } } diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/objects/WrappedWatchableObject.java b/src/main/java/dev/brighten/ac/packet/wrapper/objects/WrappedWatchableObject.java index 70e59e4..715964e 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/objects/WrappedWatchableObject.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/objects/WrappedWatchableObject.java @@ -23,7 +23,7 @@ public class WrappedWatchableObject extends WObject { private static WrappedField firstIntField, dataValueIdField, dataWatcherObjectField, dataWatcherObjectIdField, dataSerializerField, watchedObjectField, watchedField; - private int firstInt, dataValueId; + private int objectType, dataValueId; private Object watchedObject, dataWatcherObject, serializer; private boolean watched; @@ -31,13 +31,20 @@ public class WrappedWatchableObject extends WObject { super(object); } + public WrappedWatchableObject(int objectType, int dataValueId, Object watchedObject) { + super(constructor.newInstance(objectType, dataValueId, watchedObject)); + + this.dataValueId = dataValueId; + this.watchedObject = watchedObject; + } + @Override public void processVanilla() { if(ProtocolVersion.getGameVersion().isBelow(ProtocolVersion.V1_9)) { - firstInt = fetch(firstIntField); + objectType = fetch(firstIntField); dataValueId = fetch(dataValueIdField); } else { - firstInt = -1; + objectType = -1; dataWatcherObject = fetch(dataWatcherObjectField); dataValueId = dataWatcherObjectIdField.get(dataWatcherObject); serializer = dataSerializerField.get(dataWatcherObject); @@ -48,7 +55,7 @@ public class WrappedWatchableObject extends WObject { @Override public Object toVanillaObject() { - return constructor.newInstance(firstInt, dataValueId, watchedObject); + return constructor.newInstance(objectType, dataValueId, watchedObject); } static { diff --git a/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutSpawnEntityLiving.java b/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutSpawnEntityLiving.java index 2a05d98..58b3569 100644 --- a/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutSpawnEntityLiving.java +++ b/src/main/java/dev/brighten/ac/packet/wrapper/out/WPacketPlayOutSpawnEntityLiving.java @@ -3,10 +3,13 @@ package dev.brighten.ac.packet.wrapper.out; import dev.brighten.ac.Anticheat; import dev.brighten.ac.packet.wrapper.PacketType; import dev.brighten.ac.packet.wrapper.WPacket; +import dev.brighten.ac.packet.wrapper.objects.WrappedWatchableObject; import lombok.Builder; import lombok.Getter; import org.bukkit.entity.EntityType; +import java.util.List; + @Getter @Builder public class WPacketPlayOutSpawnEntityLiving extends WPacket { @@ -16,6 +19,7 @@ public class WPacketPlayOutSpawnEntityLiving extends WPacket { private double x, y, z; private float yaw, pitch, headYaw; private double motionX, motionY, motionZ; + private List watchedObjects; @Override public PacketType getPacketType() { diff --git a/src/main/java/dev/brighten/ac/utils/Base64.java b/src/main/java/dev/brighten/ac/utils/Base64.java deleted file mode 100644 index cc86cfb..0000000 --- a/src/main/java/dev/brighten/ac/utils/Base64.java +++ /dev/null @@ -1,92 +0,0 @@ -package dev.brighten.ac.utils; - -public final class Base64 { - private static final int BYTES_PER_UNENCODED_BLOCK = 3; - private static final int BYTES_PER_ENCODED_BLOCK = 4; - private static final int SIX_BIT_MASK = 63; - private static final byte PAD = 61; - private static final byte[] ENCODE_TABLE = new byte[]{65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47}; - private static final int[] DECODE_TABLE = new int[128]; - - public static byte[] decode(String s) { - int delta = s.endsWith("==") ? 2 : (s.endsWith("=") ? 1 : 0); - byte[] buffer = new byte[s.length() * 3 / 4 - delta]; - int mask = 255; - int pos = 0; - - for(int i = 0; i < s.length(); i += 4) { - int c0 = DECODE_TABLE[s.charAt(i)]; - int c1 = DECODE_TABLE[s.charAt(i + 1)]; - buffer[pos++] = (byte)((c0 << 2 | c1 >> 4) & mask); - if (pos >= buffer.length) { - return buffer; - } - - int c2 = DECODE_TABLE[s.charAt(i + 2)]; - buffer[pos++] = (byte)((c1 << 4 | c2 >> 2) & mask); - if (pos >= buffer.length) { - return buffer; - } - - int c3 = DECODE_TABLE[s.charAt(i + 3)]; - buffer[pos++] = (byte)((c2 << 6 | c3) & mask); - } - - return buffer; - } - - public static String encode(byte[] in) { - int modulus = 0; - int bitWorkArea = 0; - int numEncodedBytes = in.length / 3 * 4 + (in.length % 3 == 0 ? 0 : 4); - byte[] buffer = new byte[numEncodedBytes]; - int pos = 0; - byte[] var6 = in; - int var7 = in.length; - - for(int var8 = 0; var8 < var7; ++var8) { - int b = var6[var8]; - modulus = (modulus + 1) % 3; - if (b < 0) { - b += 256; - } - - bitWorkArea = (bitWorkArea << 8) + b; - if (0 == modulus) { - buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 18 & 63]; - buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 12 & 63]; - buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 6 & 63]; - buffer[pos++] = ENCODE_TABLE[bitWorkArea & 63]; - } - } - - switch (modulus) { - case 1: - buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 2 & 63]; - buffer[pos++] = ENCODE_TABLE[bitWorkArea << 4 & 63]; - buffer[pos++] = 61; - buffer[pos] = 61; - break; - case 2: - buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 10 & 63]; - buffer[pos++] = ENCODE_TABLE[bitWorkArea >> 4 & 63]; - buffer[pos++] = ENCODE_TABLE[bitWorkArea << 2 & 63]; - buffer[pos] = 61; - } - - return byteArrayToString(buffer); - } - - private static String byteArrayToString(byte[] buffer) { - return new String(buffer, 0, 0, buffer.length); - } - - private Base64() { - } - - static { - for(int i = 0; i < ENCODE_TABLE.length; DECODE_TABLE[ENCODE_TABLE[i]] = i++) { - } - - } -} diff --git a/src/main/java/dev/brighten/ac/utils/ExpTimer.java b/src/main/java/dev/brighten/ac/utils/ExpTimer.java deleted file mode 100644 index 4ac1ff4..0000000 --- a/src/main/java/dev/brighten/ac/utils/ExpTimer.java +++ /dev/null @@ -1,63 +0,0 @@ -package dev.brighten.ac.utils; - -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitTask; - -import java.util.concurrent.TimeUnit; - -public class ExpTimer { - public final Player player; - public long timerEnd; - public final long extense; - public final Runnable onComplete; - public BukkitTask levelTask, expTask; - private final int previousLevel; - private final float previousExp; - - public ExpTimer(Player player, long time, TimeUnit unit, Runnable onComplete) { - this.player = player; - this.extense = unit.toMillis(time); - this.timerEnd = System.currentTimeMillis() + extense; - this.onComplete = onComplete; - - previousExp = player.getExp(); - previousLevel = player.getLevel(); - levelTask = RunUtils.taskTimer(() -> { - if(getMillisLeft() <= 0) { - levelTask.cancel(); - levelTask = null; - return; - } - - player.setLevel((int)Math.floor(getMillisLeft() / 1000D)); - }, 2, 20); - expTask = RunUtils.taskTimer(() -> { - if(getMillisLeft() <= 0 && levelTask == null) { - expTask.cancel(); - expTask = null; - player.setLevel(previousLevel); - player.setExp(previousExp); - onComplete.run(); - return; - } - - player.setExp(getMillisLeft() / (float)extense); - }, 2, 2); - } - - private long getMillisLeft() { - return timerEnd - System.currentTimeMillis(); - } - - public void stop() { - timerEnd = System.currentTimeMillis(); - } - - public void cancel() { - levelTask.cancel(); - expTask.cancel(); - levelTask = expTask = null; - player.setExp(previousExp); - player.setLevel(previousLevel); - } -} diff --git a/src/main/java/dev/brighten/ac/utils/StreamUtils.java b/src/main/java/dev/brighten/ac/utils/StreamUtils.java deleted file mode 100644 index d3b90f3..0000000 --- a/src/main/java/dev/brighten/ac/utils/StreamUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -package dev.brighten.ac.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; - -public class StreamUtils { - public static void streamCopy(InputStream in, OutputStream out) throws IOException { - assert (in != null); - assert (out != null); - ReadableByteChannel inChannel = Channels.newChannel(in); - WritableByteChannel outChannel = Channels.newChannel(out); - channelCopy(inChannel, outChannel); - } - - /** - * A fast method to copy bytes from one channel to another; uses direct 16k - * buffers to minimize copies and OS overhead. - * @author http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/ - * @param src - a non-null readable bytechannel to read the data from - * @param dest - a non-null writeable byte channel to write the data to - */ - public static void channelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException { - assert (src != null); - assert (dest != null); - final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); - while (src.read(buffer) != -1) { - // prepare the buffer to be drained - buffer.flip(); - // write to the channel, may block - dest.write(buffer); - // If partial transfer, shift remainder down - // If buffer is empty, same as doing clear() - buffer.compact(); - } - - // EOF will leave buffer in fill state - buffer.flip(); - - // make sure the buffer is fully drained. - while (buffer.hasRemaining()) { - dest.write(buffer); - } - } - -}