Issues with false positives in Hitboxes remain

This commit is contained in:
2025-06-19 14:51:43 -04:00
parent 2d91ae8d96
commit f790ed8b76
26 changed files with 272 additions and 247 deletions
+1 -1
View File
@@ -83,7 +83,7 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>false</minimizeJar>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>co.aikar</pattern>
@@ -2,7 +2,6 @@ package dev.brighten.ac;
import co.aikar.commands.*;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import dev.brighten.ac.api.AnticheatAPI;
@@ -13,8 +12,6 @@ import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.data.PlayerRegistry;
import dev.brighten.ac.data.info.CheckHandler;
import dev.brighten.ac.depends.LibraryLoader;
import dev.brighten.ac.depends.MavenLibrary;
import dev.brighten.ac.depends.Repository;
import dev.brighten.ac.handler.BBRevealHandler;
import dev.brighten.ac.handler.PacketHandler;
import dev.brighten.ac.handler.entity.FakeEntityTracker;
@@ -194,7 +191,6 @@ public class Anticheat extends JavaPlugin {
this.playerRegistry = new PlayerRegistry();
this.keepaliveProcessor = new KeepaliveProcessor();
keepaliveProcessor.start();
Bukkit.getOnlinePlayers().forEach(playerRegistry::generate);
this.packetHandler = new PacketHandler();
@@ -243,7 +239,6 @@ public class Anticheat extends JavaPlugin {
PacketEvents.getAPI().terminate();
keepaliveProcessor.stop();
keepaliveProcessor.keepAlives.clear();
@@ -97,6 +97,8 @@ public class Check implements ECheck {
}
public void correctMovement(KLocation toLoc) {
if(!isCancellable()) return;
CancelResult result = CancelResult.builder().cancelled(false).build();
for (AnticheatEvent event : AnticheatAPI.INSTANCE.getAllEvents()) {
@@ -14,7 +14,7 @@ import java.util.Optional;
public class CheckManager {
private final Map<String, CheckStatic> checkClasses = new HashMap<>();
private final Map<String, String> idToName = new HashMap<>();
private final Map<Class<? extends Check>, CheckSettings> checkSettings = new HashMap<>();
private final Map<String, CheckSettings> checkSettings = new HashMap<>();
public CheckManager() {
synchronized (checkClasses) {
for (WrappedClass aClass : new ClassScanner().getClasses(CheckData.class)) {
@@ -38,10 +38,7 @@ public class CheckManager {
generateConfigSettings(checkData);
settings = Optional.of(CheckSettings.settingsFromData(checkData));
}
checkSettings.put(checkClass.getParent(), settings.get());
Anticheat.INSTANCE.alog(true, "&7Adding check to CheckManager: " + checkData.name());
checkSettings.put(checkData.checkId(), settings.get());
checkClasses.put(checkData.name(), check);
idToName.put(checkData.checkId(), checkData.name());
@@ -62,8 +59,8 @@ public class CheckManager {
return Optional.empty();
}
public CheckSettings getCheckSettings(Class<? extends Check> checkClass) {
return checkSettings.get(checkClass);
public CheckSettings getCheckSettings(String checkId) {
return checkSettings.get(checkId);
}
private void generateConfigSettings(CheckData data) {
@@ -18,4 +18,14 @@ public class CheckSettings {
.punishVl(data.punishVl())
.build();
}
@Override
public String toString() {
return "CheckSettings{" +
"enabled=" + enabled +
", punishable=" + punishable +
", cancellable=" + cancellable +
", punishVl=" + punishVl +
'}';
}
}
@@ -73,7 +73,7 @@ public class Hitbox extends Check {
final Tuple<EntityLocation, EntityLocation> eloc = optionalEloc.get();
final KLocation to = target.two;
final KLocation to = target.two.clone();
if(eloc.one.x == 0 && eloc.one.y == 0 & eloc.one.z == 0) {
return;
@@ -87,7 +87,9 @@ public class Phase extends Check {
POSITIONS.clear();
} else if(teleportLoc != null) {
final Location finalLoc = teleportLoc.clone(); // This is to make sure it isn't set null later.
Anticheat.INSTANCE.getRunUtils().task(() -> player.getBukkitPlayer().teleport(finalLoc));
if(isCancellable()) {
Anticheat.INSTANCE.getRunUtils().task(() -> player.getBukkitPlayer().teleport(finalLoc));
}
return true;
}
@@ -97,7 +99,9 @@ public class Phase extends Check {
final Location fromLoc = player.getMovement().getFrom().getLoc()
.toLocation(player.getBukkitPlayer().getWorld());
Anticheat.INSTANCE.getRunUtils().task(() -> player.getBukkitPlayer().teleport(fromLoc));
if(isCancellable()) {
Anticheat.INSTANCE.getRunUtils().task(() -> player.getBukkitPlayer().teleport(fromLoc));
}
return true;
}
@@ -136,11 +140,13 @@ public class Phase extends Check {
double totalDelta = dx + dy + dz;
if(totalDelta > 0.0001) {
Anticheat.INSTANCE.getRunUtils().task(() -> {
teleportLoc = calculatedTo
.toLocation(player.getBukkitPlayer().getWorld());
player.getBukkitPlayer().teleport(teleportLoc);
});
if(isCancellable()) {
Anticheat.INSTANCE.getRunUtils().task(() -> {
teleportLoc = calculatedTo
.toLocation(player.getBukkitPlayer().getWorld());
player.getBukkitPlayer().teleport(teleportLoc);
});
}
flag("x=%.4f, y=%.4f, z=%.4f", dx, dy, dz);
}
@@ -37,7 +37,7 @@ public class BlockA extends Check {
WrappedBlock block = player.getBlockUpdateHandler().getBlock(loc);
CollisionBox box = BlockData.getData(block.getType()).getBox(block, player.getPlayerVersion());
CollisionBox box = BlockData.getData(block.getType()).getBox(player, block, player.getPlayerVersion());
debug(packet.getBlockPosition().toString());
if(!(box instanceof final SimpleCollisionBox simpleBox)) {
@@ -168,9 +168,7 @@ public class LogsCommand extends BaseCommand {
for (String key : violations.keySet()) {
if (Anticheat.INSTANCE.getCheckManager().isCheck(key)) {
CheckSettings checkData = Anticheat.INSTANCE.getCheckManager()
.getCheckSettings(Anticheat.INSTANCE.getCheckManager().getCheckClasses()
.get(Anticheat.INSTANCE.getCheckManager().getIdToName().get(key))
.getCheckClass().getParent());
.getCheckSettings(key);
int vl = violations.get(key), maxVL = checkData.getPunishVl();
boolean developer = false;
@@ -67,16 +67,22 @@ public class CheckHandler {
for (CheckStatic toHook : TO_HOOK) {
KListener listener = toHook.playerInit(player);
CheckData data = toHook.getCheckClass().getAnnotation(CheckData.class);
String checkId = data != null ? data.checkId() : UUID.randomUUID().toString();
synchronized (EVENTS) {
for (Tuple<WrappedField, Class<?>> tuple : toHook.getActions()) {
WAction<?> action = tuple.one.get(listener);
EVENTS.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new ActionStore[] {new ActionStore(action, toHook.getCheckClass().getParent())};
return new ActionStore[] {new ActionStore(action,
toHook.getCheckClass().getParent(), checkId)};
} else {
ActionStore[] newArray = Arrays.copyOf(array, array.length + 1);
newArray[array.length] = new ActionStore(action, toHook.getCheckClass().getParent());
newArray[array.length] = new ActionStore(action,
toHook.getCheckClass().getParent(), checkId);
return newArray;
}
});
@@ -88,10 +94,12 @@ public class CheckHandler {
EVENTS_TIMESTAMP.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new TimedActionStore[] {new TimedActionStore(action, toHook.getCheckClass().getParent())};
return new TimedActionStore[] {new TimedActionStore(action,
toHook.getCheckClass().getParent(), checkId)};
} else {
TimedActionStore<?>[] newArray = Arrays.copyOf(array, array.length + 1);
newArray[array.length] = new TimedActionStore(action, toHook.getCheckClass().getParent());
newArray[array.length] = new TimedActionStore(action,
toHook.getCheckClass().getParent(), checkId);
return newArray;
}
});
@@ -105,10 +113,12 @@ public class CheckHandler {
EVENTS_CANCELLABLE.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new CancellableActionStore[] {new CancellableActionStore(action, toHook.getCheckClass().getParent())};
return new CancellableActionStore[] {new CancellableActionStore(action,
toHook.getCheckClass().getParent(), checkId)};
} else {
CancellableActionStore[] newArray = Arrays.copyOf(array, array.length + 1);
newArray[array.length] = new CancellableActionStore(action, toHook.getCheckClass().getParent());
newArray[array.length] = new CancellableActionStore(action,
toHook.getCheckClass().getParent(), checkId);
return newArray;
}
});
@@ -118,7 +128,7 @@ public class CheckHandler {
for (CheckStatic checkClass : Anticheat.INSTANCE.getCheckManager().getCheckClasses().values()) {
CheckData data = checkClass.getCheckClass().getAnnotation(CheckData.class);
String checkId = data != null ? data.checkId() : UUID.randomUUID().toString();
//Version checks
if(player.getPlayerVersion().isNewerThan(data.maxVersion()) || player.getPlayerVersion().isOlderThan(data.minVersion())) {
Anticheat.INSTANCE.alog("Player " + player.getBukkitPlayer().getName() +
@@ -130,7 +140,7 @@ public class CheckHandler {
Check check = checkClass.playerInit(player);
CheckSettings settings = Anticheat.INSTANCE.getCheckManager()
.getCheckSettings(checkClass.getCheckClass().getParent());
.getCheckSettings(checkId);
if(settings == null) {
throw new RuntimeException("Settings for check" + check.getName() + " do not exist!");
@@ -149,10 +159,10 @@ public class CheckHandler {
EVENTS.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new ActionStore[] {new ActionStore(action, checkClass.getCheckClass().getParent())};
return new ActionStore[] {new ActionStore(action, checkClass.getCheckClass().getParent(), checkId)};
} else {
ActionStore[] newArray = Arrays.copyOf(array, array.length + 1);
newArray[array.length] = new ActionStore(action, checkClass.getCheckClass().getParent());
newArray[array.length] = new ActionStore(action, checkClass.getCheckClass().getParent(), checkId);
return newArray;
}
});
@@ -164,10 +174,10 @@ public class CheckHandler {
EVENTS_TIMESTAMP.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new TimedActionStore[] {new TimedActionStore(action, checkClass.getCheckClass().getParent())};
return new TimedActionStore[] {new TimedActionStore(action, checkClass.getCheckClass().getParent(), checkId)};
} else {
TimedActionStore<?>[] newArray = Arrays.copyOf(array, array.length + 1);
newArray[array.length] = new TimedActionStore(action, checkClass.getCheckClass().getParent());
newArray[array.length] = new TimedActionStore(action, checkClass.getCheckClass().getParent(), checkId);
return newArray;
}
});
@@ -181,10 +191,10 @@ public class CheckHandler {
EVENTS_CANCELLABLE.compute(tuple.two, (packetClass, array) -> {
if (array == null) {
return new CancellableActionStore[] {new CancellableActionStore(action, checkClass.getCheckClass().getParent())};
return new CancellableActionStore[] {new CancellableActionStore(action, checkClass.getCheckClass().getParent(), checkId)};
} else {
CancellableActionStore[] newArray = Arrays.copyOf(array, array.length + 1);
newArray[array.length] = new CancellableActionStore(action, checkClass.getCheckClass().getParent());
newArray[array.length] = new CancellableActionStore(action, checkClass.getCheckClass().getParent(), checkId);
return newArray;
}
});
@@ -215,9 +225,9 @@ public class CheckHandler {
if(EVENTS.containsKey(event.getClass())) {
ActionStore<Event>[] actions = (ActionStore<Event>[]) EVENTS.get(event.getClass());
for (ActionStore<Event> action : actions) {
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass());
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckId());
if(checkSettings != null && !Anticheat.INSTANCE.getCheckManager()
.getCheckSettings(action.getCheckClass()).isEnabled())
.getCheckSettings(action.getCheckId()).isEnabled())
continue;
action.getAction().invoke(event);
@@ -233,9 +243,9 @@ public class CheckHandler {
synchronized (EVENTS) {
ActionStore<Object>[] actions = (ActionStore<Object>[]) EVENTS.get(packet.getClass());
for (ActionStore<Object> action : actions) {
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass());
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckId());
if(checkSettings != null && !Anticheat.INSTANCE.getCheckManager()
.getCheckSettings(action.getCheckClass()).isEnabled())
.getCheckSettings(action.getCheckId()).isEnabled())
continue;
action.getAction().invoke(packet);
}
@@ -246,9 +256,9 @@ public class CheckHandler {
TimedActionStore<Object>[] actions = (TimedActionStore<Object>[])
EVENTS_TIMESTAMP.get(packet.getClass());
for (TimedActionStore<Object> action : actions) {
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass());
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckId());
if(checkSettings != null && !Anticheat.INSTANCE.getCheckManager()
.getCheckSettings(action.getCheckClass()).isEnabled())
.getCheckSettings(action.getCheckId()).isEnabled())
continue;
action.getAction().invoke(packet, timestamp);
}
@@ -260,9 +270,9 @@ public class CheckHandler {
CancellableActionStore<Object>[] actions = (CancellableActionStore<Object>[])
EVENTS_CANCELLABLE.get(packet.getClass());
for (CancellableActionStore<Object> action : actions) {
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckClass());
var checkSettings = Anticheat.INSTANCE.getCheckManager().getCheckSettings(action.getCheckId());
if(checkSettings != null && !Anticheat.INSTANCE.getCheckManager()
.getCheckSettings(action.getCheckClass()).isEnabled())
.getCheckSettings(action.getCheckId()).isEnabled())
continue;
if(action.getAction().invoke(packet)) {
@@ -13,6 +13,7 @@ import java.util.UUID;
public class ActionStore<T> {
private final WAction<T> action;
private final Class<? extends Check> checkClass;
private final String checkId;
//To ensure duplicate actions are not added to the list
private final UUID uuid = UUID.randomUUID();
@@ -13,6 +13,7 @@ import java.util.UUID;
public class CancellableActionStore<T> {
private final WCancellable<T> action;
private final Class<? extends Check> checkClass;
private final String checkId;
private final UUID uuid = UUID.randomUUID();
@Override
@@ -13,6 +13,7 @@ import java.util.UUID;
public class TimedActionStore<T> {
private final WTimedAction<T> action;
private final Class<? extends Check> checkClass;
private final String checkId;
//To ensure duplicate actions are not added to the list
private final UUID uuid = UUID.randomUUID();
@@ -4,12 +4,10 @@ import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
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 io.github.retrooper.packetevents.util.SpigotConversionUtil;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.Material;
@@ -50,28 +48,20 @@ public class BBRevealHandler implements Listener {
if(player == null || !player.getWrappedPlayer().getItemInHand().isSimilar(wand)) return;
if(event.getAction() == Action.RIGHT_CLICK_BLOCK) {
if(Materials.checkFlag(SpigotConversionUtil.fromBukkitItemMaterial(event.getClickedBlock().getType()).getPlacedType()
, Materials.COLLIDABLE)) {
IntVector blockLoc = new IntVector(event.getClickedBlock().getX(),
event.getClickedBlock().getY(), event.getClickedBlock().getZ());
Set<IntVector> blocksToShow = this.blocksToShow
.computeIfAbsent(event.getPlayer().getUniqueId(), k -> new HashSet<>());
if(blocksToShow.contains(blockLoc)) {
blocksToShow.remove(blockLoc);
event.getPlayer().spigot().sendMessage(new ComponentBuilder("No longer showing block: ")
.color(ChatColor.RED).append(event.getClickedBlock().getType().name()).color(ChatColor.WHITE)
.create());
} else {
blocksToShow.add(blockLoc);
event.getPlayer().spigot().sendMessage(new ComponentBuilder("Now showing block: ")
.color(ChatColor.GREEN).append(event.getClickedBlock().getType().name()).color(ChatColor.WHITE)
.append(" (collidable=" + Materials.checkFlag(SpigotConversionUtil.fromBukkitItemMaterial(event.getClickedBlock().getType()).getPlacedType(), Materials.COLLIDABLE) + ")")
.color(ChatColor.GRAY)
.create());
}
IntVector blockLoc = new IntVector(event.getClickedBlock().getX(),
event.getClickedBlock().getY(), event.getClickedBlock().getZ());
Set<IntVector> blocksToShow = this.blocksToShow
.computeIfAbsent(event.getPlayer().getUniqueId(), k -> new HashSet<>());
if(blocksToShow.contains(blockLoc)) {
blocksToShow.remove(blockLoc);
event.getPlayer().spigot().sendMessage(new ComponentBuilder("No longer showing block: ")
.color(ChatColor.RED).append(event.getClickedBlock().getType().name()).color(ChatColor.WHITE)
.create());
} else {
event.getPlayer().spigot().sendMessage(new ComponentBuilder("Block is not collidable!")
.color(ChatColor.RED)
blocksToShow.add(blockLoc);
event.getPlayer().spigot().sendMessage(new ComponentBuilder("Now showing block: ")
.color(ChatColor.GREEN).append(event.getClickedBlock().getType().name()).color(ChatColor.WHITE)
.color(ChatColor.GRAY)
.create());
}
event.setCancelled(true);
@@ -227,6 +227,8 @@ public class MovementHandler {
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) {
@@ -360,7 +362,7 @@ public class MovementHandler {
player.getInfo().setBlockOnTo(Optional.of(player.getBlockUpdateHandler()
.getBlock(new IntVector(to.getLoc()))));
player.getInfo().setBlockBelow(Optional.of(player.getBlockUpdateHandler()
.getBlock(new IntVector(to.getLoc().subtract(0, 1, 0)))));
.getBlock(new IntVector(to.getLoc().clone().subtract(0, 1, 0)))));
if (packet.hasPositionChanged()) {
// Updating player bounding box
@@ -834,6 +836,7 @@ it
if (to.getBox().max().lengthSquared() == 0) { //Needs initializing
setTo(packet);
from.setLoc(to);
player.getBukkitPlayer().sendMessage("Initializing location");
} else {
from.setLoc(to);
setTo(packet);
@@ -333,32 +333,10 @@ public class PacketHandler {
player.getInfo().getVelocityHistory().add(velocity);
player.getInfo().setDoingVelocity(true);
player.runKeepaliveAction(ka -> player.getVelocityHandler().onPre(packet));
player.runKeepaliveAction(ka -> {
if (player.getInfo().getVelocityHistory().contains(velocity))
player.getOnVelocityTasks().forEach(task -> task.accept(velocity));
player.getVelocityHandler().onPost(packet);
if (player.getInfo().getVelocityHistory().contains(velocity)) {
player.getInfo().setDoingVelocity(false);
player.getInfo().getVelocity().reset();
synchronized (player.getInfo().getVelocityHistory()) {
player.getInfo().getVelocityHistory().remove(velocity);
}
}
}, 1);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_VELOCITY) {
WrapperPlayServerEntityVelocity packet = new WrapperPlayServerEntityVelocity(event);
wrapped = packet;
if(packet.getEntityId() == player.getBukkitPlayer().getEntityId()) {
Vector3d velocity = packet.getVelocity();
player.getInfo().getVelocityHistory().add(velocity);
player.getInfo().setDoingVelocity(true);
player.runKeepaliveAction(ka -> player.getVelocityHandler().onPre(packet));
player.runKeepaliveAction(ka -> {
player.runInstantAction(ia -> {
if(!ia.isEnd()) {
player.getVelocityHandler().onPre(packet);
} else {
if (player.getInfo().getVelocityHistory().contains(velocity))
player.getOnVelocityTasks().forEach(task -> task.accept(velocity));
@@ -370,7 +348,36 @@ public class PacketHandler {
player.getInfo().getVelocityHistory().remove(velocity);
}
}
}, 1);
}
}, true);
player.runKeepaliveAction(ka -> player.getVelocityHandler().onComplete(packet), 2);
} else if(event.getPacketType() == PacketType.Play.Server.ENTITY_VELOCITY) {
WrapperPlayServerEntityVelocity packet = new WrapperPlayServerEntityVelocity(event);
wrapped = packet;
if(packet.getEntityId() == player.getBukkitPlayer().getEntityId()) {
Vector3d velocity = packet.getVelocity();
player.getInfo().getVelocityHistory().add(velocity);
player.getInfo().setDoingVelocity(true);
player.runInstantAction(ia -> {
if (!ia.isEnd()) {
player.getVelocityHandler().onPre(packet);
} else {
if (player.getInfo().getVelocityHistory().contains(velocity))
player.getOnVelocityTasks().forEach(task -> task.accept(velocity));
player.getVelocityHandler().onPost(packet);
if (player.getInfo().getVelocityHistory().contains(velocity)) {
player.getInfo().setDoingVelocity(false);
player.getInfo().getVelocity().reset();
synchronized (player.getInfo().getVelocityHistory()) {
player.getInfo().getVelocityHistory().remove(velocity);
}
}
}
}, true);
player.runKeepaliveAction(ka -> player.getVelocityHandler().onComplete(packet), 2);
}
} else if(event.getPacketType() == PacketType.Play.Server.RESPAWN) {
wrapped = new WrapperPlayServerRespawn(event);
@@ -9,7 +9,10 @@ import dev.brighten.ac.utils.Tuple;
import lombok.RequiredArgsConstructor;
import lombok.val;
import java.util.*;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
@RequiredArgsConstructor
@@ -31,6 +34,7 @@ public class VelocityHandler {
if(packet.getEntityId() != PLAYER.getBukkitPlayer().getEntityId()) return;
VELOCITY_MAP.add(new Tuple<>(packet.getVelocity(), false));
PLAYER.getInfo().getVelocity().reset();
}
public void onPre(WrapperPlayServerExplosion packet) {
@@ -39,6 +43,7 @@ public class VelocityHandler {
if(kb == null) return;
VELOCITY_MAP.add(new Tuple<>(kb, false));
PLAYER.getInfo().getVelocity().reset();
}
public void onPost(WrapperPlayServerEntityVelocity packet) {
@@ -62,8 +67,19 @@ public class VelocityHandler {
}
}
public void onComplete(WrapperPlayServerExplosion packet) {
// If the velocity is not confirmed, remove it.
VELOCITY_MAP.removeIf(value -> value.one.equals(packet.getKnockback()));
}
public void onComplete(WrapperPlayServerEntityVelocity packet) {
// If the velocity is not confirmed, remove it.
VELOCITY_MAP.removeIf(value -> value.one.equals(packet.getVelocity()));
}
public List<Vector3d> getPossibleVectors() {
return VELOCITY_MAP.stream()
.filter(set -> !set.two)
.map(set -> set.one)
.toList();
}
@@ -1,22 +1,17 @@
package dev.brighten.ac.handler.keepalive;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPing;
import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.TransactionServerWrapper;
import dev.brighten.ac.utils.BukkitRunnable;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.shorts.Short2ObjectArrayMap;
import org.bukkit.scheduler.BukkitTask;
import java.util.Map;
import java.util.Optional;
public class KeepaliveProcessor implements BukkitRunnable {
private BukkitTask task;
public class KeepaliveProcessor {
public KeepAlive currentKeepalive = new KeepAlive((short) 0);
public short tick;
@@ -29,8 +24,7 @@ public class KeepaliveProcessor implements BukkitRunnable {
public KeepaliveProcessor() {
}
@Override
public void run(BukkitTask task) {
public void run() {
tick++;
if(tick > Short.MAX_VALUE - 2) {
@@ -76,23 +70,10 @@ public class KeepaliveProcessor implements BukkitRunnable {
return getKeepById(lastResponses.get(data.getBukkitPlayer().getUniqueId().hashCode()));
}
public void start() {
if (task == null) {
task = Anticheat.INSTANCE.getRunUtils().taskTimer(this, 20L, 0L);
}
}
public void addResponse(APlayer data, short id) {
getKeepById(id).ifPresent(ka -> {
lastResponses.put(data.getBukkitPlayer().getUniqueId().hashCode(), (Short) id);
ka.received(data);
});
}
public void stop() {
if (task != null) {
task.cancel();
task = null;
}
}
}
@@ -2,6 +2,8 @@ package dev.brighten.ac.utils;
import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.types.NoCollisionBox;
import org.bukkit.Material;
import java.util.HashMap;
@@ -33,7 +35,7 @@ public class Materials {
flag |= SOLID;
}
if(mat.isBlocking()) {
if(!(BlockData.getData(mat).getDefaultBox() instanceof NoCollisionBox)) {
flag |= COLLIDABLE;
}
@@ -38,6 +38,8 @@ public class ServerInjector {
public void onSize() {
Runnable toRun;
Anticheat.INSTANCE.getKeepaliveProcessor().run();
while((toRun = Anticheat.INSTANCE.getOnTickEnd().poll()) != null) {
toRun.run();
}
@@ -4,6 +4,7 @@ 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.world.BlockFace;
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags;
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;
@@ -13,8 +14,6 @@ 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.*;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import org.bukkit.block.Block;
import java.util.*;
import java.util.stream.Stream;
@@ -42,7 +41,7 @@ public enum BlockData {
boxes.add(new HexCollisionBox(0.0D, 0.0D, 15.0D, 16.0D, 16.0D, 16.0D));
// This is where fire differs from vine with its hitbox
if (block.getBlockState().getType() == StateTypes.FIRE && boxes.isNull())
if (block.getBlockState().getType() == com.github.retrooper.packetevents.protocol.world.states.type.StateTypes.FIRE && boxes.isNull())
return new HexCollisionBox(0.0D, 0.0D, 0.0D, 16.0D, 1.0D, 16.0D);
return boxes;
@@ -88,36 +87,80 @@ public enum BlockData {
}
}, StateTypes.ANVIL, StateTypes.CHIPPED_ANVIL, StateTypes.DAMAGED_ANVIL)
,_WALL(new DynamicWall(), StateTypes.values().stream()
.filter(mat -> mat.getName().contains("WALL"))
.toArray(StateType[]::new)),
,_WALL(new DynamicWall(), BlockTags.WALLS.getStates().toArray(new StateType[0])),
_SKULL((protocol, player, b) -> {
BlockFace face = b.getBlockState().getFacing();
return switch (face) {
case EAST -> new SimpleCollisionBox(0.25F, 0.25F, 0.5F, 0.75F, 0.75F, 1.0F);
case NORTH -> new SimpleCollisionBox(0.25F, 0.25F, 0.0F, 0.75F, 0.75F, 0.5F);
case SOUTH -> new SimpleCollisionBox(0.5F, 0.25F, 0.25F, 1.0F, 0.75F, 0.75F);
case DOWN -> new SimpleCollisionBox(0.0F, 0.25F, 0.25F, 0.5F, 0.75F, 0.75F);
default -> new SimpleCollisionBox(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F); //WEST
};
}, StateTypes.values().stream().filter(mat -> mat.getName().contains("SKULL")
|| mat.getName().contains("HEAD")).toArray(StateType[]::new)),
_SKULL(new SimpleCollisionBox(0.25F, 0.0F, 0.25F, 0.75F, 0.5F, 0.75F),
StateTypes.CREEPER_HEAD, StateTypes.ZOMBIE_HEAD, StateTypes.DRAGON_HEAD, StateTypes.PLAYER_HEAD,
StateTypes.SKELETON_SKULL, StateTypes.WITHER_SKELETON_SKULL, StateTypes.HEAVY_CORE),
_PIGLIN_SKULL(new HexCollisionBox(3.0D, 0.0D, 3.0D, 13.0D, 8.0D, 13.0D),
StateTypes.PIGLIN_HEAD),
_WALL_SKULL((protocol, player, b) -> switch (b.getBlockState().getFacing()) {
case SOUTH -> new SimpleCollisionBox(0.25F, 0.25F, 0.0F, 0.75F, 0.75F, 0.5F);
case WEST -> new SimpleCollisionBox(0.5F, 0.25F, 0.25F, 1.0F, 0.75F, 0.75F);
case EAST -> new SimpleCollisionBox(0.0F, 0.25F, 0.25F, 0.5F, 0.75F, 0.75F);
default -> new SimpleCollisionBox(0.25F, 0.25F, 0.5F, 0.75F, 0.75F, 1.0F);
}, StateTypes.CREEPER_WALL_HEAD, StateTypes.DRAGON_WALL_HEAD, StateTypes.PLAYER_WALL_HEAD, StateTypes.ZOMBIE_WALL_HEAD,
StateTypes.SKELETON_WALL_SKULL, StateTypes.WITHER_SKELETON_WALL_SKULL),
_PIGLIN_WALL_SKULL((protocol, player, b) -> switch (b.getBlockState().getFacing()) {
case SOUTH -> new HexCollisionBox(3.0D, 4.0D, 0.0D, 13.0D, 12.0D, 8.0D);
case EAST -> new HexCollisionBox(0.0D, 4.0D, 3.0D, 8.0D, 12.0D, 13.0D);
case WEST -> new HexCollisionBox(8.0D, 4.0D, 3.0D, 16.0D, 12.0D, 13.0D);
default -> new HexCollisionBox(3.0D, 4.0D, 8.0D, 13.0D, 12.0D, 16.0D);
}, StateTypes.PIGLIN_WALL_HEAD),
_DOOR(new DoorHandler(), StateTypes.values().stream()
.filter(mat -> !mat.getName().contains("TRAP") && !mat.getName().contains("ITEM")
&& mat.getName().contains("DOOR")
// Potential cause for ClassCastException to MaterialData instead of Door
&& !mat.getName().equals("WOOD_DOOR") && !mat.getName().equals("IRON_DOOR"))
.toArray(StateType[]::new)),
_DOOR(new DoorHandler(), BlockTags.DOORS.getStates().toArray(new StateType[0])),
_HOPPER(new HopperBounding(), 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.values().stream().filter(m -> m.getName().contains("CAKE")).toArray(StateType[]::new)),
}, StateTypes.CAKE),
_COCOA_BEAN((protocol, player, block) -> {
int age = block.getBlockState().getAge();
if (protocol.isNewerThanOrEquals(ClientVersion.V_1_9_1) && protocol.isOlderThan(ClientVersion.V_1_11))
age = Math.min(age, 1);
switch (block.getBlockState().getFacing()) {
case EAST:
switch (age) {
case 0:
return new HexCollisionBox(11.0D, 7.0D, 6.0D, 15.0D, 12.0D, 10.0D);
case 1:
return new HexCollisionBox(9.0D, 5.0D, 5.0D, 15.0D, 12.0D, 11.0D);
case 2:
return new HexCollisionBox(7.0D, 3.0D, 4.0D, 15.0D, 12.0D, 12.0D);
}
case WEST:
switch (age) {
case 0:
return new HexCollisionBox(1.0D, 7.0D, 6.0D, 5.0D, 12.0D, 10.0D);
case 1:
return new HexCollisionBox(1.0D, 5.0D, 5.0D, 7.0D, 12.0D, 11.0D);
case 2:
return new HexCollisionBox(1.0D, 3.0D, 4.0D, 9.0D, 12.0D, 12.0D);
}
case NORTH:
switch (age) {
case 0:
return new HexCollisionBox(6.0D, 7.0D, 1.0D, 10.0D, 12.0D, 5.0D);
case 1:
return new HexCollisionBox(5.0D, 5.0D, 1.0D, 11.0D, 12.0D, 7.0D);
case 2:
return new HexCollisionBox(4.0D, 3.0D, 1.0D, 12.0D, 12.0D, 9.0D);
}
case SOUTH:
switch (age) {
case 0:
return new HexCollisionBox(6.0D, 7.0D, 11.0D, 10.0D, 12.0D, 15.0D);
case 1:
return new HexCollisionBox(5.0D, 5.0D, 9.0D, 11.0D, 12.0D, 15.0D);
case 2:
return new HexCollisionBox(4.0D, 3.0D, 7.0D, 12.0D, 12.0D, 15.0D);
}
}
return NoCollisionBox.INSTANCE;
}, StateTypes.COCOA),
_LADDER((protocol, player, b) -> {
float var3 = 0.125F;
BlockFace facing = b.getBlockState().getFacing();
@@ -141,12 +184,9 @@ public enum BlockData {
new SimpleCollisionBox(0.375F, 0.0F, 0.0F, 0.625F, 1.5F, 1.0F);
default -> NoCollisionBox.INSTANCE;
};
}, StateTypes.values().stream().filter(mat -> mat.getName().contains("FENCE") && mat.getName().contains("GATE"))
.toArray(StateType[]::new)),
}, BlockTags.FENCE_GATES.getStates().toArray(new StateType[0])),
_FENCE(new DynamicFence(), StateTypes.values().stream()
.filter(mat -> mat.getName().equals("FENCE") || mat.getName().endsWith("FENCE"))
.toArray(StateType[]::new)),
_FENCE(new DynamicFence(), BlockTags.FENCES.getStates().toArray(new StateType[0])),
_PANE(new DynamicPane(), StateTypes.values().stream()
.filter(s -> s.getName().endsWith("PANE"))
.toArray(StateType[]::new)),
@@ -167,12 +207,9 @@ public enum BlockData {
}
return new SimpleCollisionBox(0, 0.5, 0, 1, 1, 1);
}, StateTypes.values().stream().filter(mat ->
mat.getName().contains("STEP") || mat.getName().contains("SLAB"))
.filter(mat -> !mat.getName().contains("DOUBLE"))
.toArray(StateType[]::new)),
}, BlockTags.SLABS.getStates().toArray(new StateType[0])),
_STAIR(new DynamicStair(), StateTypes.values().stream().filter(mat -> mat.getName().contains("STAIRS"))
_STAIR(new DynamicStair(), StateTypes.values().stream().filter(mat -> mat.getName().toUpperCase().contains("STAIRS"))
.toArray(StateType[]::new)),
_CHEST((protocol, player, b) -> {
@@ -221,13 +258,18 @@ public enum BlockData {
}, StateTypes.LILY_PAD),
_BED(new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.5625, 1.0F),
StateTypes.values().stream().filter(mat -> mat.getName().contains("BED") && !mat.getName().contains("ROCK"))
StateTypes.values().stream().filter(mat -> mat.getName().toUpperCase().contains("BED") && !mat.getName().toUpperCase().contains("ROCK"))
.toArray(StateType[]::new)),
_WALL_SIGN((protocol, player, block) -> switch (block.getBlockState().getFacing()) {
case NORTH, SOUTH -> new HexCollisionBox(0.0, 14.0, 6.0, 16.0, 16.0, 10.0);
case WEST, EAST -> new HexCollisionBox(6.0, 14.0, 0.0, 10.0, 16.0, 16.0);
default -> NoCollisionBox.INSTANCE;
}, BlockTags.WALL_HANGING_SIGNS.getStates().toArray(new StateType[0])),
_TRAPDOOR(new TrapDoorHandler(), StateTypes.values().stream()
.filter(mat -> mat.getName().contains("TRAP_DOOR")
|| mat.getName().contains("TRAPDOOR")).toArray(StateType[]::new)),
.filter(mat -> mat.getName().toUpperCase().contains("TRAP_DOOR")
|| mat.getName().toUpperCase().contains("TRAPDOOR")).toArray(StateType[]::new)),
_STUPID(new SimpleCollisionBox(0.0F, 0.0F, 0.0F, 1.0F, 0.125F, 1.0F),
StateTypes.COMPARATOR),
@@ -260,67 +302,30 @@ public enum BlockData {
_POT(new SimpleCollisionBox(0.3125, 0.0, 0.3125, 0.6875, 0.375, 0.6875),
StateTypes.FLOWER_POT),
_WALL_SIGN((version, player, block) -> {
double var4 = 0.28125;
double var5 = 0.78125;
double var6 = 0;
double var7 = 1.0;
double var8 = 0.125;
return switch (block.getBlockState().getFacing()) {
case NORTH -> new SimpleCollisionBox(var6, var4, 1.0 - var8, var7, var5, 1.0);
case SOUTH -> new SimpleCollisionBox(var6, var4, 0.0, var7, var5, var8);
case WEST -> new SimpleCollisionBox(1.0 - var8, var4, var6, 1.0, var5, var7);
case EAST -> new SimpleCollisionBox(0.0, var4, var6, var8, var5, var7);
default -> new SimpleCollisionBox(0, 0, 0, 1, 1, 1);
};
}, StateTypes.values().stream().filter(mat -> mat.getName().contains("WALL_SIGN"))
.toArray(StateType[]::new)),
_SIGN(new SimpleCollisionBox(0.25, 0.0, 0.25, 0.75, 1.0, 0.75),
StateTypes.values().stream().filter(m -> m.getName().endsWith("_SIGN") || m.getName().startsWith("SIGN"))
.toArray(StateType[]::new)),
_BUTTON((version, player, block) -> {
BlockFace face = block.getBlockState().getFacing();
face = face.getOppositeFace();
boolean flag = block.getBlockState().isPowered(); //is powered;
double f2 = (float)(flag ? 1 : 2) / 16.0;
return switch (face) {
case EAST -> new SimpleCollisionBox(0.0, 0.375, 0.3125, f2, 0.625, 0.6875);
case WEST -> new SimpleCollisionBox(1.0 - f2, 0.375, 0.3125, 1.0, 0.625, 0.6875);
case SOUTH -> new SimpleCollisionBox(0.3125, 0.375, 0.0, 0.6875, 0.625, f2);
case NORTH -> new SimpleCollisionBox(0.3125, 0.375, 1.0 - f2, 0.6875, 0.625, 1.0);
case UP -> new SimpleCollisionBox(0.3125, 0.0, 0.375, 0.6875, 0.0 + f2, 0.625);
case DOWN -> new SimpleCollisionBox(0.3125, 1.0 - f2, 0.375, 0.6875, 1.0, 0.625);
default -> NoCollisionBox.INSTANCE;
};
}, StateTypes.values().stream().filter(mat -> mat.getName().contains("BUTTON")).toArray(StateType[]::new)),
_LEVER((version, player, block) -> {
BlockFace face = block.getBlockState().getFacing();
double f = 0.1875;
return switch (face) {
case EAST -> new SimpleCollisionBox(0.0, 0.2, 0.5 - f, f * 2.0, 0.8, 0.5 + f);
case WEST -> new SimpleCollisionBox(1.0 - f * 2.0, 0.2, 0.5 - f, 1.0, 0.8, 0.5 + f);
case SOUTH -> new SimpleCollisionBox(0.5 - f, 0.2, 0.0, 0.5 + f, 0.8, f * 2.0);
case NORTH -> new SimpleCollisionBox(0.5 - f, 0.2, 1.0 - f * 2.0, 0.5 + f, 0.8, 1.0);
case UP -> new SimpleCollisionBox(0.25, 0.0, 0.25, 0.75, 0.6, 0.75);
case DOWN -> new SimpleCollisionBox(0.25, 0.4, 0.25, 0.75, 1.0, 0.75);
default -> NoCollisionBox.INSTANCE;
};
}, StateTypes.LEVER),
_NONE(NoCollisionBox.INSTANCE, Stream.of(StateTypes.TORCH, StateTypes.REDSTONE_TORCH,
StateTypes.REDSTONE_WIRE, StateTypes.REDSTONE_WALL_TORCH, StateTypes.POWERED_RAIL, StateTypes.WALL_TORCH,
StateTypes.RAIL, StateTypes.ACTIVATOR_RAIL, StateTypes.DETECTOR_RAIL, StateTypes.AIR, StateTypes.FERN,
StateTypes.TRIPWIRE, StateTypes.TRIPWIRE_HOOK)
StateTypes.TRIPWIRE, StateTypes.TRIPWIRE_HOOK, StateTypes.TWISTING_VINES_PLANT, StateTypes.WEEPING_VINES_PLANT,
StateTypes.TWISTING_VINES, StateTypes.WEEPING_VINES, StateTypes.CAVE_VINES, StateTypes.CAVE_VINES_PLANT,
StateTypes.TALL_SEAGRASS, StateTypes.SEAGRASS, StateTypes.SHORT_GRASS, StateTypes.FERN, StateTypes.NETHER_SPROUTS,
StateTypes.DEAD_BUSH, StateTypes.SUGAR_CANE, StateTypes.SWEET_BERRY_BUSH, StateTypes.WARPED_ROOTS,
StateTypes.CRIMSON_ROOTS, StateTypes.TORCHFLOWER_CROP, StateTypes.PINK_PETALS, StateTypes.TALL_GRASS,
StateTypes.LARGE_FERN, StateTypes.BAMBOO_SAPLING, StateTypes.HANGING_ROOTS,
StateTypes.SMALL_DRIPLEAF, StateTypes.END_PORTAL, StateTypes.LEVER, StateTypes.PUMPKIN_STEM, StateTypes.MELON_STEM,
StateTypes.ATTACHED_MELON_STEM, StateTypes.ATTACHED_PUMPKIN_STEM, StateTypes.BEETROOTS, StateTypes.POTATOES,
StateTypes.WHEAT, StateTypes.CARROTS, StateTypes.NETHER_WART, StateTypes.MOVING_PISTON, StateTypes.AIR, StateTypes.CAVE_AIR,
StateTypes.VOID_AIR, StateTypes.LIGHT, StateTypes.WATER)
.toArray(StateType[]::new)),
_NONE2(NoCollisionBox.INSTANCE, StateTypes.values().stream()
.filter(mat -> mat.getName().contains("PLATE")).toArray(StateType[]::new));
.filter(state -> state.getName().toUpperCase().contains("PLATE")
|| !(state.isSolid()
|| state == StateTypes.LAVA
|| state == StateTypes.SCAFFOLDING
|| state == StateTypes.PITCHER_CROP
|| state == StateTypes.HEAVY_CORE
|| state == StateTypes.PALE_MOSS_CARPET || BlockTags.WALL_HANGING_SIGNS.contains(state)))
.toArray(StateType[]::new));
private CollisionBox box;
private CollisionFactory dynamic;
@@ -340,28 +345,23 @@ public enum BlockData {
this.materials = mList.toArray(new StateType[0]);
}
public CollisionBox getBox(Block block, ClientVersion version) {
if (this.box != null)
return this.box.copy().offset(block.getX(), block.getY(), block.getZ());
var convert = SpigotConversionUtil.fromBukkitMaterialData(block.getState().getData());
return new DynamicCollisionBox(dynamic, null, new WrappedBlock(new IntVector(block.getLocation()),
convert.getType(),
convert),
version)
.offset(block.getX(), block.getY(), block.getZ());
public CollisionBox getDefaultBox() {
if (this.box != null) {
return this.box.copy();
} else {
return new DynamicCollisionBox(dynamic, null, null,
PacketEvents.getAPI().getServerManager().getVersion().toClientVersion());
}
}
public CollisionBox getBox(WrappedBlock block, ClientVersion version) {
if (this.box != null)
return this.box.copy().offset(block.getLocation().getX(), block.getLocation().getY(), block.getLocation().getZ());
return new DynamicCollisionBox(dynamic, null, block, version)
.offset(block.getLocation().getX(), block.getLocation().getY(), block.getLocation().getZ());
public CollisionBox getBox(APlayer player, WrappedBlock block, ClientVersion version) {
return getBox(player, block.getLocation(), version);
}
public CollisionBox getBox(APlayer player, IntVector block, ClientVersion version) {
if (this.box != null)
return this.box.copy().offset(block.getX(), block.getY(), block.getZ());
return new DynamicCollisionBox(dynamic, null, player.getBlockUpdateHandler().getBlock(block), version)
return new DynamicCollisionBox(dynamic, player, player.getBlockUpdateHandler().getBlock(block), version)
.offset(block.getX(), block.getY(), block.getZ());
}
@@ -369,12 +369,14 @@ public enum BlockData {
static {
for (BlockData data : values()) {
for (StateType mat : data.materials) lookup.put(mat, data);
for (StateType state : data.materials) {
lookup.put(state, data);
}
}
}
public static BlockData getData(StateType material) {
BlockData data = lookup.get(material);
public static BlockData getData(StateType state) {
BlockData data = lookup.get(state);
return data != null ? data : _DEFAULT;
}
}
@@ -35,7 +35,7 @@ public class DynamicStair implements CollisionFactory {
private static EnumShape getStairsShape(APlayer player, WrappedBlock originalStairs) {
BlockFace facing = originalStairs.getBlockState().getFacing();
Optional<WrappedBlock> offsetOne = BlockUtils.getRelative(player, originalStairs.getLocation(), facing);
Optional<WrappedBlock> offsetOne = player == null ? Optional.empty() : BlockUtils.getRelative(player, originalStairs.getLocation(), facing);
if(offsetOne.isEmpty()) return EnumShape.STRAIGHT;
@@ -56,7 +56,7 @@ public class DynamicWall implements CollisionFactory {
}
private static boolean wallConnects(ClientVersion v, APlayer player, WrappedBlock fenceBlock, BlockFace direction) {
Optional<WrappedBlock> targetBlock = BlockUtils.getRelative(player, fenceBlock.getLocation(), direction, 1);
Optional<WrappedBlock> targetBlock = player == null ? Optional.empty() : BlockUtils.getRelative(player, fenceBlock.getLocation(), direction, 1);
if(targetBlock.isEmpty()) return false;
@@ -7,12 +7,12 @@ import com.github.retrooper.packetevents.protocol.world.states.type.StateType;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.handler.block.WrappedBlock;
import dev.brighten.ac.utils.Helper;
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.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector;
@@ -138,12 +138,11 @@ public class RayCollision implements CollisionBox {
Helper.drawRay(this, 3, particle, Arrays.asList(players));
}
public List<CollisionBox> boxesOnRay(APlayer world, double distance) {
public List<CollisionBox> 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.
List<CollisionBox> boxes = new ArrayList<>();
boolean primaryThread = Bukkit.isPrimaryThread();
ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
for (int i = 0; i < locs.length; i++) {
@@ -153,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 = world.getBlockUpdateHandler().getBlock(fx, fy, fz);
WrappedBlock block = player.getBlockUpdateHandler().getBlock(fx, fy, fz);
if (block == null) continue;
@@ -161,7 +160,7 @@ public class RayCollision implements CollisionBox {
if (!type.isBlocking()) continue;
CollisionBox box = BlockData.getData(type).getBox(block, version);
CollisionBox box = BlockData.getData(type).getBox(player, block, version);
if (!isCollided(box)) continue;
@@ -171,11 +170,10 @@ public class RayCollision implements CollisionBox {
return boxes;
}
public WrappedBlock getClosestBlockOfType(APlayer world, int bitmask, double distance) {
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 to prevent NegativeArraySizeException.
boolean primaryThread = Bukkit.isPrimaryThread();
Location[] locs = new Location[Math.max(2, amount)]; //We do a max
ClientVersion version = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
for (int i = 0; i < locs.length; i++) {
@@ -185,15 +183,15 @@ public class RayCollision implements CollisionBox {
int fy = MathHelper.floor_double(originY + (directionY * ix));
int fz = MathHelper.floor_double(originZ + (directionZ * ix));
WrappedBlock block = world.getBlockUpdateHandler().getBlock(fx, fy, fz);
WrappedBlock block = player.getBlockUpdateHandler().getBlock(fx, fy, fz);
if (block == null) continue;
if(block == null || !Materials.checkFlag(block.getType(), bitmask)) continue;
final StateType type = block.getType();
if (!type.isBlocking()) continue;
CollisionBox box = BlockData.getData(type).getBox(block, version);
CollisionBox box = BlockData.getData(type).getBox(player, block, version);
if (!isCollided(box)) continue;
+1 -1
View File
@@ -1,5 +1,5 @@
name: Kauri
version: 3.0-DEV
version: 3.0
main : dev.brighten.ac.Anticheat
author: funkemunky
softdepend: [ViaVersion, ProtocolSupport]
@@ -63,10 +63,13 @@ public class KLocation implements Cloneable {
return new Location(world, x, y, z, yaw, pitch);
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public KLocation clone() {
return new KLocation(x, y, z, yaw, pitch, timeStamp);
try {
return (KLocation) super.clone();
} catch (CloneNotSupportedException e) {
return new KLocation(x, y, z, yaw, pitch, timeStamp);
}
}
public double distanceSquared(KLocation other) {