Adding Velocity checking and new Velocity (A)

This commit is contained in:
Dawson
2022-08-15 17:30:23 -04:00
parent e937ef794a
commit afeae529f5
18 changed files with 555 additions and 283 deletions
@@ -58,6 +58,8 @@ public class Anticheat extends JavaPlugin {
private RollingAverageDouble tps = new RollingAverageDouble(4, 20);
private final Map<UUID, WorldInfo> worldInfoMap = new HashMap<>();
public static boolean allowDebug = true;
@ConfigSetting(path = "logging", name = "verbose")
private static boolean verboseLogging = true;
+23 -1
View File
@@ -5,10 +5,14 @@ import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.MathUtils;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.Tuple;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.MillisTimer;
import lombok.Getter;
import lombok.val;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
@@ -26,7 +30,7 @@ public abstract class Check {
public static List<UUID> alertsEnabled = new ArrayList<>();
public static final Map<String, List<UUID>> debugInstances = new HashMap<>();
public static final Map<String, List<Tuple<UUID, UUID>>> debugInstances = new HashMap<>();
public Check(APlayer player) {
this.player = player;
@@ -48,7 +52,25 @@ public abstract class Check {
}
public void debug(String information, Object... variables) {
if(!Anticheat.allowDebug) return;
if(debugInstances.containsKey(checkData.name())) {
val list = debugInstances.get(checkData.name());
for (Tuple<UUID, UUID> tuple : list) {
UUID toDebug = tuple.one;
if(!toDebug.equals(player.getUuid())) continue;
ComponentBuilder builder = new ComponentBuilder("[DEBUG] ").color(ChatColor.RED);
BaseComponent[] message =
builder.append(String.format(information, variables)).color(ChatColor.GRAY).create();
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(tuple.two)
.ifPresent(player -> player.getBukkitPlayer().spigot().sendMessage(message));
}
}
}
public void flag(String information, Object... variables) {
@@ -55,4 +55,10 @@ public class CheckManager {
checkClasses.add(check);
}
public boolean isCheck(String name) {
final String formattedName = name.replace("_", " ");
return checkClasses.stream().anyMatch(c -> c.getCheckClass().getAnnotation(CheckData.class).name()
.equalsIgnoreCase(formattedName));
}
}
@@ -24,33 +24,22 @@ public class Aim extends Check {
public void flying(WPacketPlayInFlying packet) {
if(!packet.isLooked()) return;
final float sens = getPlayer().getMovement().getSensitivityMcp(),
deltaYaw = Math.abs(getPlayer().getMovement().getDeltaYaw()),
deltaPitch = Math.abs(getPlayer().getMovement().getDeltaPitch());
final float deltaX = deltaYaw / getPlayer().getMovement().getYawMode();
final float deltaY = deltaPitch / getPlayer().getMovement().getPitchMode();
if(getPlayer().getMovement().getYawGcdList().size() < 40)
return;
final double gridX = getGrid(getPlayer().getMovement().getYawGcdList()),
gridY = getGrid(getPlayer().getMovement().getPitchGcdList());
if(gridX < 0.005 || gridY < 0.005) lastGrid.reset();
if(deltaX > 200 || deltaY > 200) {
if(getPlayer().getMovement().getYawGcdList().size() < 40
|| getPlayer().getMovement().getLookX() > 200 || getPlayer().getMovement().getLookY() > 200) {
if(buffer > 0) buffer--;
return;
}
if(getPlayer().getMovement().getPitchGCD() < 0.007
&& lastGrid.isPassed()
&& getPlayer().getMovement().getLastHighRate().isNotPassed(3)) {
if(deltaPitch < 10 && ++buffer > 8) {
flag("%s", getPlayer().getMovement().getPitchGCD());
&& !getPlayer().getMovement().isCinematic()) {
if(Math.abs(getPlayer().getMovement().getDeltaPitch()) < 10 && ++buffer > 4) {
flag("gcd=%.5f", getPlayer().getMovement().getPitchGCD());
}
getPlayer().getBukkitPlayer().sendMessage("Flagged b:" + buffer);
} else buffer = 0;
debug("b=%s gcd=%.4f cin=%s", buffer, getPlayer().getMovement().getPitchGCD(),
getPlayer().getMovement().isCinematic());
}
/*
@@ -26,10 +26,11 @@ public class FlyA extends Check {
@Action
public void onFlying(WPacketPlayInFlying packet) {
if(!packet.isMoved() || (getPlayer().getMovement().getDeltaXZ() == 0
&& getPlayer().getMovement().getDeltaY() == 0))
&& getPlayer().getMovement().getDeltaY() == 0)) {
return;
}
boolean onGround = getPlayer().getMovement().getTo().isOnGround(),
boolean onGround = getPlayer().getMovement().getTo().isOnGround() && getPlayer().getBlockInformation().blocksBelow,
fromGround = getPlayer().getMovement().getFrom().isOnGround();
double lDeltaY = fromGround ? 0 : getPlayer().getMovement().getLDeltaY();
double predicted = onGround ? lDeltaY : (lDeltaY - 0.08) * mult;
@@ -53,7 +54,10 @@ public class FlyA extends Check {
double deltaPredict = MathUtils.getDelta(getPlayer().getMovement().getDeltaY(), predicted);
if(!getPlayer().getInfo().isGeneralCancel() && deltaPredict > 0.016) {
if(!getPlayer().getInfo().isGeneralCancel()
&& getPlayer().getInfo().getBlockAbove().isPassed(1)
&& !getPlayer().getInfo().isOnLadder()
&& !getPlayer().getBlockInformation().onSlime && deltaPredict > 0.016) {
if(++buffer > 5) {
buffer = 5;
flag("dY=%.3f p=%.3f dx=%.3f", getPlayer().getMovement().getDeltaY(), predicted,
@@ -0,0 +1,57 @@
package dev.brighten.ac.check.impl.velocity;
import dev.brighten.ac.check.Action;
import dev.brighten.ac.check.Check;
import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.check.CheckType;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.wrapper.in.WPacketPlayInFlying;
import org.bukkit.util.Vector;
@CheckData(name = "Velocity (A)", type = CheckType.MOVEMENT)
public class VelocityA extends Check {
private Vector currentVelocity = null;
private float buffer = 0;
public VelocityA(APlayer player) {
super(player);
player.onVelocity(velocity -> {
currentVelocity = velocity.clone();
debug("did velocity: " + currentVelocity.getY());
});
}
@Action
public void onFlying(WPacketPlayInFlying packet) {
if(currentVelocity != null && currentVelocity.getY() > 0
&& !getPlayer().getBlockInformation().inWeb
&& !getPlayer().getBlockInformation().onClimbable
&& getPlayer().getInfo().getBlockAbove().isPassed(6)
&& !getPlayer().getBlockInformation().onSlime
&& !getPlayer().getInfo().isGeneralCancel()) {
double pct = getPlayer().getMovement().getDeltaY() / currentVelocity.getY() * 100;
if(pct < 99.999 || pct > 400) {
if(++buffer > 15) {
flag("pct=%.1f%% buffer=%.1f", pct, buffer);
}
} else if(buffer > 0) buffer-= 0.5;
debug("pct=%.1f%% buffer=%.1f dy=%.4f vy=%.4f", pct, buffer,
getPlayer().getMovement().getDeltaY(), currentVelocity.getY());
currentVelocity.setY((currentVelocity.getY() - 0.08) * 0.98);
if(currentVelocity.getY() < 0.005
|| getPlayer().getBlockInformation().collidesHorizontally
|| getPlayer().getBlockInformation().collidesVertically
|| getPlayer().getInfo().getVelocity().isPassed(7))
currentVelocity = null;
} else if(currentVelocity != null) {
debug("not null: " + currentVelocity.getY());
}
}
}
@@ -8,16 +8,17 @@ import dev.brighten.ac.check.CheckData;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.messages.Messages;
import dev.brighten.ac.packet.handler.HandlerAbstract;
import dev.brighten.ac.utils.Color;
import dev.brighten.ac.utils.Init;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.Priority;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.msg.ChatBuilder;
import io.netty.buffer.Unpooled;
import lombok.val;
import net.minecraft.server.v1_8_R3.PacketDataSerializer;
import net.minecraft.server.v1_8_R3.PacketPlayOutCustomPayload;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.stream.Collectors;
@@ -31,7 +32,7 @@ public class AnticheatCommand extends BaseCommand {
.getCommandCompletions();
cc.registerCompletion("checks", (c) -> Anticheat.INSTANCE.getCheckManager().getCheckClasses().stream()
.map(cs -> cs.getCheckClass().getAnnotation(CheckData.class).name())
.map(cs -> cs.getCheckClass().getAnnotation(CheckData.class).name().replace(" ", "_"))
.sorted(Comparator.naturalOrder()).collect(Collectors.toList()));
BukkitCommandContexts contexts = (BukkitCommandContexts) Anticheat.INSTANCE.getCommandManager()
@@ -48,6 +49,29 @@ public class AnticheatCommand extends BaseCommand {
+ "Argument \"%s\" is not an integer", arg));
}
});
contexts.registerOptionalContext(APlayer.class, c -> {
if(c.hasFlag("other")) {
String arg = c.popFirstArg();
Player onlinePlayer = Bukkit.getPlayer(arg);
if(onlinePlayer != null) {
return Anticheat.INSTANCE.getPlayerRegistry().getPlayer(onlinePlayer.getUniqueId())
.orElse(null);
} else return null;
} else {
CommandSender sender = c.getSender();
if(sender instanceof Player) {
return Anticheat.INSTANCE.getPlayerRegistry().getPlayer(((Player) sender).getUniqueId())
.orElse(null);
}
else if(!c.isOptional()) throw new InvalidCommandArgument(MessageKeys.NOT_ALLOWED_ON_CONSOLE,
false, new String[0]);
else return null;
}
});
}
@HelpCommand
@@ -84,9 +108,8 @@ public class AnticheatCommand extends BaseCommand {
@Syntax("[player]")
@CommandCompletion("@players")
@CommandPermission("anticheat.command.info")
public void onCommand(CommandSender sender, @Single Player target) {
public void onCommand(CommandSender sender, @Single APlayer player) {
Anticheat.INSTANCE.getScheduler().execute(() -> {
APlayer player = Anticheat.INSTANCE.getPlayerRegistry().getPlayer(target.getUniqueId()).orElse(null);
if(player == null) {
sender.spigot().sendMessage(Messages.NULL_APLAYER);
@@ -119,4 +142,50 @@ public class AnticheatCommand extends BaseCommand {
});
});
}
@Subcommand("debug")
@CommandCompletion("@checks|none @players")
@Description("Debug a player")
@CommandPermission("anticheat.command.debug")
public void onDebug(APlayer sender, @Single String check, @Optional APlayer targetPlayer) {
APlayer target = targetPlayer != null ? targetPlayer : sender;
if(check.equals("none")) {
synchronized (Check.debugInstances) {
Check.debugInstances.forEach((nameKey, list) -> {
val iterator = list.iterator();
while(iterator.hasNext()) {
val tuple = iterator.next();
if(tuple.one.equals(target.getUuid())) {
iterator.remove();
sender.getBukkitPlayer().spigot()
.sendMessage(new ChatBuilder(
"&cTurned off debug for check &f%s &con target &f%s", nameKey,
target.getBukkitPlayer().getName()).build());
}
}
});
}
} else {
if(!Anticheat.INSTANCE.getCheckManager().isCheck(check)) {
sender.getBukkitPlayer().sendMessage(Color.Red + "Check \"" + check + "\" is not a valid check!");
return;
}
synchronized (Check.debugInstances) {
Check.debugInstances.compute(check.replace("_", " "), (key, list) -> {
if(list == null) list = new ArrayList<>();
list.add(new Tuple<>(target.getUuid(), sender.getUuid()));
return list;
});
sender.getBukkitPlayer().spigot()
.sendMessage(new ChatBuilder(
"&aTurned on debug for check &f%s &con target &f%s",
check.replace("_", " "),
target.getBukkitPlayer().getName()).build());
}
}
}
}
@@ -28,6 +28,7 @@ import lombok.val;
import net.minecraft.server.v1_8_R3.PacketPlayOutTransaction;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
@@ -71,6 +72,8 @@ public class APlayer {
@Getter
private final Deque<Object> packetQueue = new LinkedList<>();
@Getter
private final List<Consumer<Vector>> onVelocityTasks = new ArrayList<>();
@Setter
@Getter
@@ -157,6 +160,10 @@ public class APlayer {
return id;
}
public void onVelocity(Consumer<Vector> runnable) {
onVelocityTasks.add(runnable);
}
public void runInstantAction(Consumer<InstantAction> runnable) {
runInstantAction(runnable, false);
@@ -192,4 +199,17 @@ public class APlayer {
public void addPlayerTick() {
playerTick++;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
APlayer aPlayer = (APlayer) o;
return Objects.equals(uuid, aPlayer.uuid);
}
@Override
public int hashCode() {
return Objects.hash(uuid);
}
}
@@ -4,6 +4,7 @@ import dev.brighten.ac.Anticheat;
import dev.brighten.ac.data.APlayer;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.*;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.BlockData;
import dev.brighten.ac.utils.world.CollisionBox;
import dev.brighten.ac.utils.world.EntityData;
@@ -15,10 +16,7 @@ import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.*;
public class BlockInformation {
private APlayer player;
@@ -138,183 +136,186 @@ public class BlockInformation {
break start;
}
if(y > 400 || y < -50) continue;
Block block = chunk.getBlock(x & 15, y, z & 15);
final Material type = block.getType();
if (type != Material.AIR) {
blocks.add(block);
final Deque<Material> types =
player.getBlockUpdateHandler().getPossibleMaterials(new IntVector(x, y, z));
CollisionBox blockBox = BlockData.getData(type)
.getBox(block, player.getPlayerVersion());
for (Material type : types) {
if (type != Material.AIR) {
BlockUtils.getBlockAsync(new Location(world, x, y, z)).ifPresent(blocks::add);
if(blockBox.isCollided(normalBox)) {
if(type.equals(cobweb))
inWeb = true;
else if(type.equals(scaffolding)) inScaffolding = true;
else if(type.equals(honey)) inHoney = true;
}
CollisionBox blockBox = BlockData.getData(type)
.getBox(world, new IntVector(x, y, z), player.getPlayerVersion());
if(type.equals(rosebush))
roseBush = true;
if(normalBox.copy().offset(0, 0.6f, 0).isCollided(blockBox))
blocksAbove = true;
if(normalBox.copy().expand(1, -0.0001, 1).isIntersected(blockBox))
blocksNear = true;
if(normalBox.copy().expand(0.1, 0, 0.1)
.offset(0, 1,0).isCollided(blockBox)) {
synchronized (aboveCollisions) {
blockBox.downCast(aboveCollisions);
}
}
if(normalBox.copy().expand(0.1, 0, 0.1).offset(0, -1, 0)
.isCollided(blockBox)) {
synchronized (belowCollisions) {
blockBox.downCast(belowCollisions);
if(blockBox.isCollided(normalBox)) {
if(type.equals(cobweb))
inWeb = true;
else if(type.equals(scaffolding)) inScaffolding = true;
else if(type.equals(honey)) inHoney = true;
}
if(Materials.checkFlag(type, Materials.FENCE)
|| Materials.checkFlag(type, Materials.WALL)) {
fenceBelow = true;
}
}
if(type.equals(rosebush))
roseBush = true;
if(Materials.checkFlag(type, Materials.SOLID)) {
SimpleCollisionBox groundBox = normalBox.copy()
.offset(0, -.49, 0).expandMax(0, -1.2, 0);
if(normalBox.copy().offset(0, 0.6f, 0).isCollided(blockBox))
blocksAbove = true;
XMaterial blockMaterial = getXMaterial(type);
if(normalBox.copy().expand(1, -0.0001, 1).isIntersected(blockBox))
blocksNear = true;
if(normalBox.copy().expand(0.4, 0, 0.4).expandMin(0, -1, 0)
.isIntersected(blockBox))
blocksBelow = true;
if(normalBox.isIntersected(blockBox)) inBlock = true;
SimpleCollisionBox box = player.getMovement().getTo().getBox().copy();
box.expand(Math.abs(player.getMovement().getDeltaX()) + 0.1, -0.001,
Math.abs(player.getMovement().getDeltaZ()) + 0.1);
if (blockBox.isCollided(box))
collidesHorizontally = true;
box = player.getMovement().getTo().getBox().copy();
box.expand(0, 0.1, 0);
if (blockBox.isCollided(box))
collidesVertically = true;
if(groundBox.copy().expandMin(0, -0.8, 0).expand(0.2, 0, 0.2)
.isIntersected(blockBox))
player.getInfo().setNearGround(true);
if(groundBox.isCollided(blockBox)) {
player.getInfo().setServerGround(true);
if(blockMaterial != null)
switch (blockMaterial) {
case ICE:
case BLUE_ICE:
case FROSTED_ICE:
case PACKED_ICE: {
onIce = true;
break;
}
case SOUL_SAND: {
onSoulSand = true;
break;
}
case SLIME_BLOCK: {
onSlime = true;
break;
}
if(normalBox.copy().expand(0.1, 0, 0.1)
.offset(0, 1,0).isCollided(blockBox)) {
synchronized (aboveCollisions) {
blockBox.downCast(aboveCollisions);
}
}
if(player.getMovement().getDeltaY() > 0
&& player.getPlayerVersion().isBelow(ProtocolVersion.V1_14)
&& Materials.checkFlag(type, Materials.LADDER)
&& normalBox.copy().expand(0.2f, 0, 0.2f)
if(normalBox.copy().expand(0.1, 0, 0.1).offset(0, -1, 0)
.isCollided(blockBox)) {
onClimbable = true;
}
synchronized (belowCollisions) {
blockBox.downCast(belowCollisions);
}
if(blockMaterial != null) {
switch (blockMaterial) {
case PISTON:
case PISTON_HEAD:
case MOVING_PISTON:
case STICKY_PISTON: {
if(normalBox.copy().expand(0.5, 0.5, 0.5)
.isCollided(blockBox))
pistonNear = true;
break;
}
if(Materials.checkFlag(type, Materials.FENCE)
|| Materials.checkFlag(type, Materials.WALL)) {
fenceBelow = true;
}
}
if(groundBox.copy().expand(0.5, 0.3, 0.5).isCollided(blockBox)) {
if(Materials.checkFlag(type, Materials.SLABS))
onSlab = true;
else
if(Materials.checkFlag(type, Materials.STAIRS))
onStairs = true;
else
if(Materials.checkFlag(type, Materials.SOLID)) {
SimpleCollisionBox groundBox = normalBox.copy()
.offset(0, -.49, 0).expandMax(0, -1.2, 0);
XMaterial blockMaterial = getXMaterial(type);
if(normalBox.copy().expand(0.4, 0, 0.4).expandMin(0, -1, 0)
.isIntersected(blockBox))
blocksBelow = true;
if(normalBox.isIntersected(blockBox)) inBlock = true;
SimpleCollisionBox box = player.getMovement().getTo().getBox().copy();
box.expand(Math.abs(player.getMovement().getDeltaX()) + 0.1, -0.001,
Math.abs(player.getMovement().getDeltaZ()) + 0.1);
if (blockBox.isCollided(box))
collidesHorizontally = true;
box = player.getMovement().getTo().getBox().copy();
box.expand(0, 0.1, 0);
if (blockBox.isCollided(box))
collidesVertically = true;
if(groundBox.copy().expandMin(0, -0.8, 0).expand(0.2, 0, 0.2)
.isIntersected(blockBox))
player.getInfo().setNearGround(true);
if(groundBox.isCollided(blockBox)) {
player.getInfo().setServerGround(true);
if(blockMaterial != null)
switch (blockMaterial) {
case ICE:
case BLUE_ICE:
case FROSTED_ICE:
case PACKED_ICE: {
onIce = true;
break;
}
case SOUL_SAND: {
onSoulSand = true;
break;
}
case SLIME_BLOCK: {
onSlime = true;
break;
}
}
}
if(player.getMovement().getDeltaY() > 0
&& player.getPlayerVersion().isBelow(ProtocolVersion.V1_14)
&& Materials.checkFlag(type, Materials.LADDER)
&& normalBox.copy().expand(0.2f, 0, 0.2f)
.isCollided(blockBox)) {
onClimbable = true;
}
if(blockMaterial != null) {
switch (blockMaterial) {
case PISTON:
case PISTON_HEAD:
case MOVING_PISTON:
case STICKY_PISTON: {
if(normalBox.copy().expand(0.5, 0.5, 0.5)
.isCollided(blockBox))
pistonNear = true;
break;
}
}
}
if(groundBox.copy().expand(0.5, 0.3, 0.5).isCollided(blockBox)) {
if(Materials.checkFlag(type, Materials.SLABS))
onSlab = true;
else
if(Materials.checkFlag(type, Materials.STAIRS))
onStairs = true;
else
if(blockMaterial != null)
switch(blockMaterial) {
case CAKE:
case BREWING_STAND:
case FLOWER_POT:
case PLAYER_HEAD:
case PLAYER_WALL_HEAD:
case SKELETON_SKULL:
case CREEPER_HEAD:
case DRAGON_HEAD:
case ZOMBIE_HEAD:
case ZOMBIE_WALL_HEAD:
case CREEPER_WALL_HEAD:
case DRAGON_WALL_HEAD:
case WITHER_SKELETON_SKULL:
case LANTERN:
case SKELETON_WALL_SKULL:
case WITHER_SKELETON_WALL_SKULL:
case SNOW: {
miscNear = true;
break;
}
case BLACK_BED:
case BLUE_BED:
case BROWN_BED:
case CYAN_BED:
case GRAY_BED:
case GREEN_BED:
case LIME_BED:
case MAGENTA_BED:
case ORANGE_BED:
case PINK_BED:
case PURPLE_BED:
case RED_BED:
case WHITE_BED:
case YELLOW_BED:
case LIGHT_BLUE_BED:
case LIGHT_GRAY_BED: {
bedNear = true;
break;
}
}
}
} else if(blockBox.isCollided(normalBox)) {
XMaterial blockMaterial = getXMaterial(type);
if(blockMaterial != null)
switch(blockMaterial) {
case CAKE:
case BREWING_STAND:
case FLOWER_POT:
case PLAYER_HEAD:
case PLAYER_WALL_HEAD:
case SKELETON_SKULL:
case CREEPER_HEAD:
case DRAGON_HEAD:
case ZOMBIE_HEAD:
case ZOMBIE_WALL_HEAD:
case CREEPER_WALL_HEAD:
case DRAGON_WALL_HEAD:
case WITHER_SKELETON_SKULL:
case LANTERN:
case SKELETON_WALL_SKULL:
case WITHER_SKELETON_WALL_SKULL:
case SNOW: {
miscNear = true;
break;
switch(blockMaterial) {
case END_PORTAL:
case NETHER_PORTAL: {
inPortal = true;
break;
}
}
case BLACK_BED:
case BLUE_BED:
case BROWN_BED:
case CYAN_BED:
case GRAY_BED:
case GREEN_BED:
case LIME_BED:
case MAGENTA_BED:
case ORANGE_BED:
case PINK_BED:
case PURPLE_BED:
case RED_BED:
case WHITE_BED:
case YELLOW_BED:
case LIGHT_BLUE_BED:
case LIGHT_GRAY_BED: {
bedNear = true;
break;
}
}
}
} else if(blockBox.isCollided(normalBox)) {
XMaterial blockMaterial = getXMaterial(type);
if(blockMaterial != null)
switch(blockMaterial) {
case END_PORTAL:
case NETHER_PORTAL: {
inPortal = true;
break;
}
}
}
}
}
@@ -1,6 +1,7 @@
package dev.brighten.ac.data.handlers;
import dev.brighten.ac.utils.PastLocation;
import dev.brighten.ac.utils.objects.evicting.EvictingList;
import dev.brighten.ac.utils.timer.Timer;
import dev.brighten.ac.utils.timer.impl.TickTimer;
import lombok.Getter;
@@ -8,6 +9,7 @@ import lombok.Setter;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.List;
@@ -19,10 +21,11 @@ public class GeneralInformation {
private Optional<Block> blockOnTo, blockBelow;
private Timer lastMove = new TickTimer(), vehicleSwitch = new TickTimer(),
lastSneak = new TickTimer(), velocity = new TickTimer(),
lastElytra = new TickTimer();
lastElytra = new TickTimer(), blockAbove = new TickTimer();
private LivingEntity target;
private boolean serverGround, lastServerGround, nearGround, worldLoaded, generalCancel, inVehicle, creative,
sneaking, sprinting, gliding, riptiding;
sneaking, sprinting, gliding, riptiding, wasOnSlime, onLadder, doingVelocity;
private List<Entity> nearbyEntities = Collections.emptyList();
private PastLocation targetPastLocation = new PastLocation();
private List<Vector> velocityHistory = Collections.synchronizedList(new EvictingList<>(5));
}
@@ -36,11 +36,11 @@ public class MovementHandler {
@Getter
private float lookX, lookY, lastLookX, lastLookY;
@Getter
private float deltaYaw, deltaPitch, lDeltaYaw, lDeltaPitch, smoothYaw, smoothPitch, lsmoothYaw, lsmoothPitch, pitchGCD, lastPitchGCD, yawGCD, lastYawGCD;
private float deltaYaw, deltaPitch, lDeltaYaw, lDeltaPitch, pitchGCD, lastPitchGCD, yawGCD, lastYawGCD;
private int moveTicks;
private final List<KLocation> posLocs = new ArrayList<>();
@Getter
private boolean checkMovement, accurateYawData, cinematicMode;
private boolean checkMovement, accurateYawData, cinematic;
@Getter
@Setter
private boolean excuseNextFlying;
@@ -57,10 +57,11 @@ public class MovementHandler {
private float sensitivityX, sensitivityY, currentSensX, currentSensY, sensitivityMcp, yawMode, pitchMode;
@Getter
private int sensXPercent, sensYPercent;
private int ticks;
private double lastX, lastY, lastLastY, lastYawAcelleration, lastPitchAcelleration;
private boolean inTick;
@Getter
private TickTimer lastCinematic = new TickTimer(2);
private MouseFilter mxaxis = new MouseFilter(), myaxis = new MouseFilter();
private float smoothCamFilterX, smoothCamFilterY, smoothCamYaw, smoothCamPitch;
private Timer lastReset = new TickTimer(2), generalProcess = new TickTimer(3);
private final EvictingList<Integer> sensitivitySamples = new EvictingList<>(50);
@@ -71,12 +72,11 @@ public class MovementHandler {
checkMovement = MovementUtils.checkMovement(player.getPlayerConnection());
if(checkMovement) {
if (checkMovement) {
moveTicks++;
}
else moveTicks = 0;
} else moveTicks = 0;
if(moveTicks > 0) {
if (moveTicks > 0) {
updateLocations(packet);
// Updating block locations
@@ -84,19 +84,28 @@ public class MovementHandler {
.getBlockAsync(to.getLoc().toLocation(player.getBukkitPlayer().getWorld())));
player.getInfo().setBlockBelow(BlockUtils
.getBlockAsync(to.getLoc().toLocation(player.getBukkitPlayer().getWorld())
.subtract(0,1,0)));
.subtract(0, 1, 0)));
if(packet.isMoved()) {
if (packet.isMoved()) {
// Updating player bounding box
player.getInfo().getLastMove().reset();
player.getInfo().setOnLadder(MovementUtils.isOnLadder(player));
}
player.getBlockInformation().runCollisionCheck();
if(player.getBlockInformation().blocksAbove) {
player.getInfo().getBlockAbove().reset();
}
}
processVelocity();
checkForTeleports(packet);
if (packet.isLooked()) {
process();
float deltaYaw = Math.abs(this.deltaYaw), lastDeltaYaw = Math.abs(this.lDeltaYaw);
final double differenceYaw = Math.abs(this.deltaYaw - lastDeltaYaw);
final double differencePitch = Math.abs(this.deltaPitch - this.lDeltaPitch);
@@ -117,9 +126,9 @@ public class MovementHandler {
val origin = this.to.getLoc().clone();
origin.y+= player.getInfo().isSneaking() ? 1.54 : 1.62;
origin.y += player.getInfo().isSneaking() ? 1.54 : 1.62;
if(lastTeleport.isPassed(1)) {
if (lastTeleport.isPassed(1)) {
predictionHandling:
{
float yawGcd = this.yawGCD,
@@ -132,7 +141,7 @@ public class MovementHandler {
if (this.pitchGCD > 0.01 && this.pitchGCD < 1.2)
pitchGcdList.add(pitchGcd);
if(yawGcdList.size() < 20 || pitchGcdList.size() < 20) {
if (yawGcdList.size() < 20 || pitchGcdList.size() < 20) {
accurateYawData = false;
break predictionHandling;
}
@@ -150,7 +159,8 @@ public class MovementHandler {
sensXPercent = sensToPercent(sensitivityX = getSensitivityFromYawGCD(yawMode));
sensYPercent = sensToPercent(sensitivityY = getSensitivityFromPitchGCD(pitchMode));
table: {
table:
{
sensitivitySamples.add(Math.max(sensXPercent, sensYPercent));
if (sensitivitySamples.size() > 30) {
@@ -167,50 +177,6 @@ public class MovementHandler {
lookX = getExpiermentalDeltaX(player);
lookY = getExpiermentalDeltaY(player);
if ((this.pitchGCD < 0.006 && this.yawGCD < 0.006) && smoothCamFilterY < 1E6
&& smoothCamFilterX < 1E6 && player.getCreation().isPassed(1000L)) {
float sens = MovementHandler.percentToSens(95);
float f = sens * 0.6f + .2f;
float f1 = f * f * f * 8;
float f2 = lookX * f1;
float f3 = lookY * f1;
smoothCamFilterX = mxaxis.smooth(smoothCamYaw, .05f * f1);
smoothCamFilterY = myaxis.smooth(smoothCamPitch, .05f * f1);
this.smoothCamYaw += f2;
this.smoothCamPitch += f3;
f2 = smoothCamFilterX * 0.5f;
f3 = smoothCamFilterY * 0.5f;
//val clampedFrom = (Math.abs(this.from.yaw) > 360 ? this.from.yaw % 360 : this.from.yaw);
val clampedFrom = MathUtils.yawTo180F(getFrom().getLoc().yaw);
float pyaw = clampedFrom + f2 * .15f;
float ppitch = this.getFrom().getLoc().pitch - f3 * .15f;
this.lsmoothYaw = smoothYaw;
this.lsmoothPitch = smoothPitch;
this.smoothYaw = pyaw;
this.smoothPitch = ppitch;
float yaccel = Math.abs(this.deltaYaw) - Math.abs(this.lDeltaYaw),
pAccel = Math.abs(this.deltaPitch) - Math.abs(this.lDeltaPitch);
if (MathUtils.getDelta(smoothYaw, clampedFrom) > (yaccel > 0 ? (yaccel > 10 ? 2.5 : 1) : 0.3)
|| MathUtils.getDelta(smoothPitch, this.getFrom().getLoc().pitch)
> (pAccel > 0 ? (pAccel > 10 ? 2.5 : 1) : 0.3)) {
smoothCamYaw = smoothCamPitch = 0;
this.cinematicMode = false;
mxaxis.reset();
myaxis.reset();
} else this.cinematicMode = true;
} else {
mxaxis.reset();
myaxis.reset();
this.cinematicMode = false;
}
lastLookX = lookX;
lastLookY = lookY;
lookX = getExpiermentalDeltaX(player);
@@ -222,6 +188,10 @@ public class MovementHandler {
}
}
if (player.getInfo().isServerGround()) {
player.getInfo().setWasOnSlime(player.getBlockInformation().onSlime);
}
player.getInfo().setCreative(player.getBukkitPlayer().getGameMode() == GameMode.CREATIVE
|| player.getBukkitPlayer().getGameMode() == GameMode.SPECTATOR);
@@ -232,8 +202,8 @@ public class MovementHandler {
player.getInfo().setGliding(CompatHandler.getInstance().isGliding(player.getBukkitPlayer()));
// Resetting glide/sneak timers
if(player.getInfo().isGliding()) player.getInfo().getLastElytra().reset();
if(player.getInfo().isSneaking()) player.getInfo().getLastSneak().reset();
if (player.getInfo().isGliding()) player.getInfo().getLastElytra().reset();
if (player.getInfo().isSneaking()) player.getInfo().getLastSneak().reset();
player.getInfo().setGeneralCancel(player.getBukkitPlayer().getAllowFlight()
|| moveTicks == 0
@@ -250,8 +220,9 @@ public class MovementHandler {
/*
ata.playerInfo.generalCancel = data.getPlayer().getAllowFlight()
|| this.creative
|| hasLevi
|| this.creativelastLastY
|| hasLeviit
it
|| data.excuseNextFlying
|| data.getPlayer().isSleeping()
|| (this.lastGhostCollision.isNotPassed() && this.lastBlockPlace.isPassed(2))
@@ -270,6 +241,21 @@ public class MovementHandler {
|| Kauri.INSTANCE.lastTickLag.isNotPassed(5);
*/
}
// generate a method that processes velocityHistory and compares to current deltaY.
private void processVelocity() {
//Iterate through player.getInfo().getVelocityHistory() and compare to current deltaY.
val iterator = player.getInfo().getVelocityHistory().iterator();
while (iterator.hasNext()) {
val velocity = iterator.next();
if(Math.abs(velocity.getY() - getDeltaY()) < 0.01) {
player.getInfo().getVelocity().reset();
player.getOnVelocityTasks().forEach(vectorConsumer -> vectorConsumer.accept(velocity));
iterator.remove();
break;
}
}
}
private static float getDeltaX(float yawDelta, float gcd) {
return MathHelper.ceiling_float_int(yawDelta / gcd);
@@ -278,6 +264,54 @@ public class MovementHandler {
private static float getDeltaY(float pitchDelta, float gcd) {
return MathHelper.ceiling_float_int(pitchDelta / gcd);
}
public void process() {
float yawAcelleration = Math.abs(getDeltaYaw());
float pitchAcelleration = Math.abs(getDeltaPitch());
// They are not rotating
if (yawAcelleration < 0.002 || pitchAcelleration < 0.002) return;
// Deltas between the current acelleration and last
double x = Math.abs(yawAcelleration - this.lastYawAcelleration);
double y = Math.abs(pitchAcelleration - this.lastPitchAcelleration);
// Deltas between last X & Y
double deltaX = Math.abs(x - this.lastX);
double deltaY = Math.abs(y - this.lastY);
// Pitch delta change
double pitchChangeAcelleration = Math.abs(this.lastLastY - deltaY);
this.inTick = false;
// we have to check something different for pitch due to it being a little harder to check for being smooth
if (x < .04 || y < .04
|| (pitchAcelleration > .08 && pitchChangeAcelleration > 0
&& !MathUtils.isScientificNotation(pitchChangeAcelleration)
&& pitchChangeAcelleration < .0855)) {
if (this.isInvalidGCD()) {
this.ticks += (this.ticks < 20 ? 1 : 0);
}
} else {
this.ticks -= this.ticks > 0 ? 1 : 0;
}
this.lastLastY = deltaY;
this.lastX = x;
this.lastY = y;
this.lastYawAcelleration = yawAcelleration;
this.lastPitchAcelleration = pitchAcelleration;
this.cinematic = this.ticks > 5;
if(cinematic) lastCinematic.reset();
}
boolean isInvalidGCD() {
return pitchGCD < 0.0078125;
}
public static float getExpiermentalDeltaX(APlayer data) {
float deltaPitch = data.getMovement().getDeltaYaw();
@@ -291,11 +325,11 @@ public class MovementHandler {
}
public double[] getEyeHeights() {
if(player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_14)) {
return new double[] {0.4f, 1.27f, 1.62f};
} else if(player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
return new double[] {0.4f, 1.54f, 1.62f};
} else return new double[] {1.54f, 1.62f};
if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_14)) {
return new double[]{0.4f, 1.27f, 1.62f};
} else if (player.getPlayerVersion().isOrAbove(ProtocolVersion.V1_9)) {
return new double[]{0.4f, 1.54f, 1.62f};
} else return new double[]{1.54f, 1.62f};
}
public static float getExpiermentalDeltaY(APlayer data) {
@@ -322,7 +356,7 @@ public class MovementHandler {
}
private static float getSensitivityFromPitchGCD(float gcd) {
return ((float)Math.cbrt(pitchToF3(gcd) / 8f) - .2f) / .6f;
return ((float) Math.cbrt(pitchToF3(gcd) / 8f) - .2f) / .6f;
}
private static float getF1FromYaw(float gcd) {
@@ -344,7 +378,7 @@ public class MovementHandler {
private static float getF1FromPitch(float gcd) {
float f = getFFromPitch(gcd);
return (float)Math.pow(f, 3) * 8;
return (float) Math.pow(f, 3) * 8;
}
private static float yawToF2(float yawDelta) {
@@ -360,20 +394,20 @@ public class MovementHandler {
int i = 0;
KLocation loc = new KLocation(packet.getX(), packet.getY(), packet.getZ(),
packet.getYaw(), packet.getPitch());
if(packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.X)) {
loc.x+= player.getMovement().getTo().getLoc().x;
if (packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.X)) {
loc.x += player.getMovement().getTo().getLoc().x;
}
if(packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.Y)) {
loc.y+= player.getMovement().getTo().getLoc().y;
if (packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.Y)) {
loc.y += player.getMovement().getTo().getLoc().y;
}
if(packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.Z)) {
loc.z+= player.getMovement().getTo().getLoc().z;
if (packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.Z)) {
loc.z += player.getMovement().getTo().getLoc().z;
}
if(packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.X_ROT)) {
loc.pitch+= player.getMovement().getTo().getLoc().pitch;
if (packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.X_ROT)) {
loc.pitch += player.getMovement().getTo().getLoc().pitch;
}
if(packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.Y_ROT)) {
loc.yaw+= player.getMovement().getTo().getLoc().yaw;
if (packet.getFlags().contains(WPacketPlayOutPosition.EnumPlayerTeleportFlags.Y_ROT)) {
loc.yaw += player.getMovement().getTo().getLoc().yaw;
}
teleportsToConfirm++;
@@ -387,6 +421,7 @@ public class MovementHandler {
/**
* Updating the "to" and "from" location to current location.
* Resetting position tracking; meant primarily for instant teleports.
*
* @param location Location
*/
public void moveTo(Location location) {
@@ -407,19 +442,19 @@ public class MovementHandler {
}
private void checkForTeleports(WPacketPlayInFlying packet) {
if(packet.isMoved() && packet.isLooked() && !packet.isOnGround()) {
if (packet.isMoved() && packet.isLooked() && !packet.isOnGround()) {
synchronized (posLocs) {
Iterator<KLocation> iterator = posLocs.iterator();
//Iterating through the ArrayList to find a potential teleport. We can't remove from the list
//without causing a CME unless we use Iterator#remove().
while(iterator.hasNext()) {
while (iterator.hasNext()) {
KLocation posLoc = iterator.next();
KLocation to = new KLocation(packet.getX(), packet.getY(), packet.getZ());
double distance = MathUtils.getDistanceWithoutRoot(to, posLoc);
if(distance < 1E-9) {
if (distance < 1E-9) {
lastTeleport.reset();
iterator.remove();
break;
@@ -427,7 +462,7 @@ public class MovementHandler {
}
//Ensuring the list doesn't overflow with old locations, a potential crash exploit.
if(teleportsToConfirm == 0 && posLocs.size() > 0) {
if (teleportsToConfirm == 0 && posLocs.size() > 0) {
posLocs.clear();
}
}
@@ -436,16 +471,17 @@ public class MovementHandler {
/**
* Setting the to and from to current location only if the player either moved or looked.
*
* @param packet WPacketPlayInFlyingh
*/
private void setTo(WPacketPlayInFlying packet) {
to.setWorld(player.getBukkitPlayer().getWorld());
if(packet.isMoved()) {
if (packet.isMoved()) {
to.getLoc().x = packet.getX();
to.getLoc().y = packet.getY();
to.getLoc().z = packet.getZ();
}
if(packet.isLooked()) {
if (packet.isLooked()) {
to.getLoc().yaw = packet.getYaw();
to.getLoc().pitch = packet.getPitch();
}
@@ -456,6 +492,7 @@ public class MovementHandler {
/**
* If from location is null, update to loc after to is set, otherwise, update to before from.
* Updates the location of player and its general delta movement.
*
* @param packet WPacketPlayInFlying
*/
private void updateLocations(WPacketPlayInFlying packet) {
@@ -16,6 +16,7 @@ import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle;
import net.minecraft.server.v1_8_R3.PacketPlayInTransaction;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.util.Vector;
import java.util.*;
@@ -127,7 +128,25 @@ public class PacketHandler {
break;
}
case VELOCITY: {
player.runKeepaliveAction(ka -> player.getInfo().getVelocity().reset());
WPacketPlayOutEntityVelocity packet = (WPacketPlayOutEntityVelocity) packetObject;
if(packet.getEntityId() == player.getBukkitPlayer().getEntityId()) {
Vector velocity = new Vector(packet.getDeltaX(), packet.getDeltaY(), packet.getDeltaZ());
player.getInfo().getVelocityHistory().add(velocity);
player.runInstantAction(ka -> {
if(!ka.isEnd()) {
player.getInfo().setDoingVelocity(true);
} else if(player.getInfo().getVelocityHistory().contains(velocity)) {
player.getInfo().getVelocityHistory().remove(velocity);
player.getOnVelocityTasks().forEach(task -> task.accept(velocity));
player.getInfo().setDoingVelocity(false);
player.getInfo().getVelocity().reset();
} else {
player.getInfo().setDoingVelocity(false);
}
});
}
break;
}
case SERVER_POSITION: {
@@ -34,4 +34,6 @@ public interface PacketConverter {
WPacketPlayOutBlockChange processBlockChange(Object object);
WPacketPlayOutMultiBlockChange processMultiBlockChange(Object object);
WPacketPlayOutEntityVelocity processVelocity(Object object);
}
@@ -124,6 +124,8 @@ public enum PacketType {
return convert.processBlockChange(object);
case MULTI_BLOCK_CHANGE:
return convert.processMultiBlockChange(object);
case VELOCITY:
return convert.processVelocity(object);
default:
return object;
}
@@ -291,4 +291,27 @@ public class Processor_18 implements PacketConverter {
.changes(blockChanges)
.build();
}
@Override
public WPacketPlayOutEntityVelocity processVelocity(Object object) {
PacketPlayOutEntityVelocity packet = (PacketPlayOutEntityVelocity) object;
PacketDataSerializer serial = serialize(packet);
return WPacketPlayOutEntityVelocity.builder()
.entityId(serial.e())
.deltaX(serial.readShort() / 8000D)
.deltaY(serial.readShort() / 8000D)
.deltaZ(serial.readShort() / 8000D)
.build();
}
private PacketDataSerializer serialize(Packet packet) {
PacketDataSerializer serial = new PacketDataSerializer(Unpooled.buffer());
try {
packet.b(serial);
} catch (IOException e) {
throw new RuntimeException(e);
}
return serial;
}
}
@@ -33,6 +33,10 @@ public class MathUtils {
current - (float)Math.floor(current / previous) * previous);
}
public static boolean isScientificNotation(double value) {
return String.valueOf(value).contains("E");
}
public static double getDistanceWithoutRoot(KLocation one, KLocation two) {
double deltaX = one.x - two.x, deltaY = one.y - two.y, deltaZ = one.z - two.z;
@@ -5,6 +5,7 @@
package dev.brighten.ac.utils.msg;
import dev.brighten.ac.utils.Color;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.*;
import net.md_5.bungee.api.chat.ComponentBuilder.FormatRetention;
@@ -14,7 +15,7 @@ public class ChatBuilder {
private ComponentBuilder componentBuilder;
public ChatBuilder(String text, Object... objects) {
this.componentBuilder = new ComponentBuilder(String.format(text, objects));
this.componentBuilder = new ComponentBuilder(String.format(Color.translate(text), objects));
}
public ChatBuilder text(String text, Object... objects) {
@@ -1,12 +1,15 @@
package dev.brighten.ac.utils.world;
import dev.brighten.ac.packet.ProtocolVersion;
import dev.brighten.ac.utils.BlockUtils;
import dev.brighten.ac.utils.MiscUtils;
import dev.brighten.ac.utils.ReflectionsUtil;
import dev.brighten.ac.utils.XMaterial;
import dev.brighten.ac.utils.math.IntVector;
import dev.brighten.ac.utils.world.blocks.*;
import dev.brighten.ac.utils.world.types.*;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@@ -437,6 +440,14 @@ public enum BlockData {
return new DynamicCollisionBox(dynamic, block, version).offset(block.getX(), block.getY(), block.getZ());
}
public CollisionBox getBox(World world, IntVector block, ProtocolVersion version) {
if (this.box != null)
return this.box.copy().offset(block.getX(), block.getY(), block.getZ());
return new DynamicCollisionBox(dynamic,
BlockUtils.getBlockAsync(block.toBukkitVector().toLocation(world)).orElse(null), version)
.offset(block.getX(), block.getY(), block.getZ());
}
private static BlockData[] lookup = new BlockData[Material.values().length];
static {