From 2636e4f997f4342fa8ed7d73f8309d8100304dfd Mon Sep 17 00:00:00 2001 From: Dawson Date: Thu, 19 Jun 2025 15:48:16 -0400 Subject: [PATCH] Updating Entity Location handler to handle full entity emulation --- .../ac/handler/EntityLocationHandler.java | 57 ++++++++--------- .../brighten/ac/handler/PacketHandler.java | 64 +++++++++++++++++++ .../brighten/ac/handler/entity/FakeMob.java | 5 +- .../ac/handler/entity/TrackedEntity.java | 16 +++++ 4 files changed, 109 insertions(+), 33 deletions(-) create mode 100644 Anticheat/src/main/java/dev/brighten/ac/handler/entity/TrackedEntity.java diff --git a/Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java b/Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java index 179b487..564590a 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/EntityLocationHandler.java @@ -10,6 +10,7 @@ import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEn import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.handler.entity.FakeMob; +import dev.brighten.ac.handler.entity.TrackedEntity; import dev.brighten.ac.packet.WPacketPlayOutEntity; import dev.brighten.ac.utils.EntityLocation; import dev.brighten.ac.utils.KLocation; @@ -20,6 +21,7 @@ import dev.brighten.ac.utils.timer.impl.MillisTimer; import dev.brighten.ac.utils.world.types.RayCollision; import io.github.retrooper.packetevents.util.SpigotConversionUtil; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.val; import org.bukkit.Location; @@ -35,7 +37,7 @@ public class EntityLocationHandler { private final APlayer data; - private final Map> entityLocationMap = new ConcurrentHashMap<>(); + private final Map> entityLocationMap = new ConcurrentHashMap<>(); private final Map> fakeMobs = new Int2ObjectArrayMap<>(); private final Map fakeMobToEntityId = new Int2ObjectArrayMap<>(); private final Timer lastFlying = new MillisTimer(); @@ -44,6 +46,9 @@ public class EntityLocationHandler { public int streak; public AtomicBoolean clientHasEntity = new AtomicBoolean(false); + @Getter + private Map trackedEntities = new Int2ObjectArrayMap<>(); + private final Set allowedEntityTypes = Set.of(EntityTypes.ZOMBIE, EntityTypes.SHEEP, EntityTypes.BLAZE, EntityTypes.SKELETON, EntityTypes.PLAYER, EntityTypes.VILLAGER, EntityTypes.IRON_GOLEM, EntityTypes.WITCH, EntityTypes.COW, EntityTypes.CREEPER); @@ -106,12 +111,7 @@ public class EntityLocationHandler { * @param packet WrappedOutRelativePosition */ void onRelPosition(WPacketPlayOutEntity packet) { - Optional op = Anticheat.INSTANCE.getWorldInfo(data.getBukkitPlayer().getWorld()) - .getEntity(packet.getId()); - - if(op.isEmpty()) return; - - Entity entity = op.get(); + TrackedEntity entity = trackedEntities.get(packet.getId()); var type = SpigotConversionUtil.fromBukkitEntityType(entity.getType()); @@ -148,18 +148,11 @@ public class EntityLocationHandler { * @param packet WrappedOutEntityTeleportPacket */ void onTeleportSent(WrapperPlayServerEntityTeleport packet) { - Optional op = Anticheat.INSTANCE.getWorldInfo(data.getBukkitPlayer().getWorld()) - .getEntity(packet.getEntityId()); + TrackedEntity entity = trackedEntities.get(packet.getEntityId()); - if(op.isEmpty()) return; + if(!allowedEntityTypes.contains(entity.getEntityType())) return; - Entity entity = op.get(); - - EntityType type = PacketEventsUtil.convertBukkitEntityType(entity.getType()); - - if(type == null || !allowedEntityTypes.contains(type)) return; - - val tuple = entityLocationMap.computeIfAbsent(entity.getUniqueId(), + val tuple = entityLocationMap.computeIfAbsent(entity.getEntityId(), key -> { createFakeMob(packet.getEntityId(), entity.getLocation()); return new Tuple<>(new EntityLocation(entity), null); @@ -216,25 +209,27 @@ public class EntityLocationHandler { * @param entity Entity * @param action Runnable */ - private void runAction(Entity entity, Runnable action) { + private void runAction(TrackedEntity entity, Runnable action) { data.runKeepaliveAction(keepalive -> action.run()); data.runKeepaliveAction(keepalive -> - entityLocationMap.get(entity.getUniqueId()).two = null, 1); + entityLocationMap.get(entity.getEntityId()).two = null, 1); } public void onEntityDestroy(WrapperPlayServerDestroyEntities packet) { - for(int id : packet.getEntityIds()) { - if(fakeMobs.containsKey(id)) { - List mobs = fakeMobs.get(id); + data.runKeepaliveAction(ka -> { + for(int id : packet.getEntityIds()) { + if(fakeMobs.containsKey(id)) { + List mobs = fakeMobs.get(id); - for (FakeMob mob : mobs) { - mob.despawn(); - fakeMobToEntityId.remove(mob.getEntityId()); + for (FakeMob mob : mobs) { + mob.despawn(); + fakeMobToEntityId.remove(mob.getEntityId()); + } + fakeMobs.remove(id); + clientHasEntity.set(false); } - fakeMobs.remove(id); - clientHasEntity.set(false); } - } + }); } public void removeFakeMob(int id) { @@ -252,7 +247,7 @@ public class EntityLocationHandler { private static final double[] offsets = new double[]{-1.25, 0, 1.25}; - private void createFakeMob(int entityId, Location location) { + private void createFakeMob(int entityId, KLocation location) { if(!canCreateMob.contains(entityId)) return; List mobs = new ArrayList<>(); @@ -286,7 +281,7 @@ public class EntityLocationHandler { EntityData entityData = new EntityData<>(7, EntityDataTypes.INT, 5); types.add(entityData); - mob.spawn(true, point.toLocation(location.getWorld()), types, data); + mob.spawn(true, new KLocation(point.getX(), point.getY(), point.getZ()), types, data); fakeMobToEntityId.put(mob.getEntityId(), data.getBukkitPlayer().getEntityId()); @@ -326,7 +321,7 @@ public class EntityLocationHandler { if(fakeMobs == null) { if(!rel) { - createFakeMob(entityId, new Location(data.getBukkitPlayer().getWorld(), x, y, z)); + createFakeMob(entityId, new KLocation(x, y, z)); } return; } 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 3a5f601..ae2dee3 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/PacketHandler.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/PacketHandler.java @@ -2,6 +2,7 @@ package dev.brighten.ac.handler; import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.event.PacketSendEvent; +import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.github.retrooper.packetevents.protocol.item.ItemStack; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.protocol.player.ClientVersion; @@ -17,6 +18,7 @@ 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.handler.entity.TrackedEntity; import dev.brighten.ac.packet.PlayerCapabilities; import dev.brighten.ac.packet.TransactionClientWrapper; import dev.brighten.ac.packet.WPacketPlayOutEntity; @@ -27,6 +29,7 @@ import io.github.retrooper.packetevents.util.SpigotConversionUtil; import lombok.val; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; +import org.checkerframework.checker.units.qual.K; import java.util.Optional; @@ -442,6 +445,67 @@ public class PacketHandler { wrapped = packet; player.getEntityLocationHandler().onRelPosition(new WPacketPlayOutEntity(packet)); + } else if(event.getPacketType() == PacketType.Play.Server.SPAWN_ENTITY) { + WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event); + wrapped = packet; + + double x = packet.getPosition().getX(); + double y = packet.getPosition().getY(); + double z = packet.getPosition().getZ(); + + player.getEntityLocationHandler().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) { + WrapperPlayServerSpawnLivingEntity packet = new WrapperPlayServerSpawnLivingEntity(event); + + wrapped = packet; + + double x = packet.getPosition().getX(); + double y = packet.getPosition().getY(); + double z = packet.getPosition().getZ(); + + player.getEntityLocationHandler().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) { + WrapperPlayServerSpawnPlayer packet = new WrapperPlayServerSpawnPlayer(event); + + wrapped = packet; + + double x = packet.getPosition().getX(); + double y = packet.getPosition().getY(); + double z = packet.getPosition().getZ(); + + + player.getEntityLocationHandler().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) { + WrapperPlayServerSpawnPainting packet = new WrapperPlayServerSpawnPainting(event); + + wrapped = packet; + + int x = packet.getPosition().getX(); + int y = packet.getPosition().getY(); + int z = packet.getPosition().getZ(); + + player.getEntityLocationHandler().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); + } else if(event.getPacketType() == PacketType.Play.Server.ENTITY_METADATA) { + wrapped = new WrapperPlayServerEntityMetadata(event); + }else if(event.getPacketType() == PacketType.Play.Server.DESTROY_ENTITIES) { + WrapperPlayServerDestroyEntities packet = new WrapperPlayServerDestroyEntities(event); + + wrapped = packet; + + player.getEntityLocationHandler().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/entity/FakeMob.java b/Anticheat/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java index 6c6130f..49936e9 100644 --- a/Anticheat/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/entity/FakeMob.java @@ -11,6 +11,7 @@ import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSp import dev.brighten.ac.Anticheat; import dev.brighten.ac.data.APlayer; import dev.brighten.ac.packet.WPacketPlayOutEntity; +import dev.brighten.ac.utils.KLocation; import lombok.Getter; import org.bukkit.Location; @@ -43,11 +44,11 @@ public class FakeMob { } */ - public void spawn(boolean invisible, Location location, APlayer... players) { + public void spawn(boolean invisible, KLocation location, APlayer... players) { spawn(invisible, location, new ArrayList<>(), players); } - public void spawn(boolean invisible, Location location, List> objects, APlayer... players) { + public void spawn(boolean invisible, KLocation location, List> objects, APlayer... players) { if(!watching.isEmpty()) { despawn(); } 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 new file mode 100644 index 0000000..f00ecf7 --- /dev/null +++ b/Anticheat/src/main/java/dev/brighten/ac/handler/entity/TrackedEntity.java @@ -0,0 +1,16 @@ +package dev.brighten.ac.handler.entity; + +import com.github.retrooper.packetevents.protocol.entity.type.EntityType; +import dev.brighten.ac.utils.KLocation; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@AllArgsConstructor +@Getter +@Setter +public class TrackedEntity { + private int entityId; + private EntityType entityType; + private KLocation location; +}