Updating Entity Location handler to handle full entity emulation

This commit is contained in:
2025-06-19 15:48:16 -04:00
parent df84a5cfe7
commit 2636e4f997
4 changed files with 109 additions and 33 deletions
@@ -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<UUID, Tuple<EntityLocation, EntityLocation>> entityLocationMap = new ConcurrentHashMap<>();
private final Map<Integer, Tuple<EntityLocation, EntityLocation>> entityLocationMap = new ConcurrentHashMap<>();
private final Map<Integer, List<FakeMob>> fakeMobs = new Int2ObjectArrayMap<>();
private final Map<Integer, Integer> 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<Integer, TrackedEntity> trackedEntities = new Int2ObjectArrayMap<>();
private final Set<EntityType> 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<Entity> 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<Entity> 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<FakeMob> mobs = fakeMobs.get(id);
data.runKeepaliveAction(ka -> {
for(int id : packet.getEntityIds()) {
if(fakeMobs.containsKey(id)) {
List<FakeMob> 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<FakeMob> 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;
}
@@ -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));
@@ -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<EntityData<?>> objects, APlayer... players) {
public void spawn(boolean invisible, KLocation location, List<EntityData<?>> objects, APlayer... players) {
if(!watching.isEmpty()) {
despawn();
}
@@ -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;
}