Skip to content

Commit

Permalink
#5 Speed check fixes, violation data timeout + new command.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrekt committed Aug 17, 2021
1 parent fa99379 commit 4ead29d
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/main/java/me/vrekt/arc/Arc.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public final class Arc extends PluginBase {
/**
* IPL version
*/
public static final String VERSION_STRING = "1.6.2-81621a-nukkit";
public static final String VERSION_STRING = "1.6.3-81721a-nukkit";

/**
* The instance of this class
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/me/vrekt/arc/check/combat/FastClick.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public FastClick() {
.build();

addConfigurationValue("max-swing-packets-per-second", 12);
addConfigurationValue("max-block-swing-packets", 25);
addConfigurationValue("max-block-swing-packets", 30);
addConfigurationValue("min-swing-delta", 50);
addConfigurationValue("min-last-block-interact-required", 500);
addConfigurationValue("cancel-attacks", true);
Expand Down Expand Up @@ -112,7 +112,7 @@ public boolean check(Player player, CombatData data, boolean wasBlockInteract, l
&& !result.failed()) {
result.setFailed("Too many block swings per second")
.withParameter("swings", data.getTotalBlockInteracts())
.withParameter("max", maxPacketsPerSecond);
.withParameter("max", maxBlockSwingPackets);
// we do not need to cancel attacks here.
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/me/vrekt/arc/check/moving/Flight.java
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ private void checkVerticalMove(Player player, MovingData data, Location ground,
.withParameter("vertical", vertical)
.withParameter("time", data.ascendingTime())
.withParameter("max", (maxAscendTime + modifier));
handleCheckViolationAndReset(player, result, from);
handleCheckViolationAndReset(player, result, ground);
}
}
}
Expand Down
47 changes: 13 additions & 34 deletions src/main/java/me/vrekt/arc/check/moving/Phase.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
import cn.nukkit.math.AxisAlignedBB;
import cn.nukkit.math.SimpleAxisAlignedBB;
import cn.nukkit.math.Vector3;
import cn.nukkit.utils.TextFormat;
import me.vrekt.arc.check.Check;
import me.vrekt.arc.check.CheckType;
import me.vrekt.arc.check.result.CheckResult;
import me.vrekt.arc.compatibility.block.BlockAccess;
import me.vrekt.arc.data.moving.MovingData;
import me.vrekt.arc.utility.block.model.BlockModel;
import me.vrekt.arc.utility.block.model.models.*;
import me.vrekt.arc.utility.block.ray.AxisRayTracing;

/**
* Checks if the player is moving through blocks.
Expand Down Expand Up @@ -56,47 +58,24 @@ public boolean check(Player player, MovingData data) {
final long now = System.currentTimeMillis();
final long timeSinceLastCollision = now - data.getLastCollisionEvent();

final AxisAlignedBB bb = player.boundingBox.grow(-0.3, 0.0, -0.3);
final AxisAlignedBB bb = player.boundingBox.grow(-0.25, 0.0, -0.25);
final CheckResult result = new CheckResult();

int minX = Math.min(from.getFloorX(), (int) bb.getMaxX());
int maxX = Math.max(from.getFloorX(), (int) bb.getMaxX());
int minY = Math.min(from.getFloorY(), (int) bb.getMaxY());
int maxY = Math.max(from.getFloorY(), (int) bb.getMaxY());
int minZ = Math.min(from.getFloorZ(), (int) bb.getMaxZ());
int maxZ = Math.max(from.getFloorZ(), (int) bb.getMaxZ());
final AxisRayTracing rayTracing = new AxisRayTracing();

boolean hasAnyBlocks = false;
for (int z = minZ; z <= maxZ; ++z) {
for (int x = minX; x <= maxX; ++x) {
for (int y = minY; y <= maxY; ++y) {
final Block block = player.getLevel().getBlock(x, y, z);
if (block.getId() != 0) {
hasAnyBlocks = checkBlockState(block, bb, safe, to, result);
rayTracing.set(safe, to, bb);
rayTracing.loop();

if (hasAnyBlocks) {
result.setFailed("Attempted to move through a solid block.")
.withParameter("blockId", block.getId());
handleCheckViolationAndReset(player, result, safe);
break;
}
}
}
if (rayTracing.collides()) {
data.setLastCollisionEvent(System.currentTimeMillis());
player.sendMessage(TextFormat.RED + "FLAG");
player.teleport(safe);
} else {
if (System.currentTimeMillis() - data.getLastCollisionEvent() >= 2000 && data.onGround()) {
data.setSafePhaseLocation(from);
}
}

// Ensure player does not have possible blocks between safe locations.
// This prevents stuff like really fast speeds, (hopefully)
final boolean safeToUpdate = !hasAnyBlocks
&& data.onGround()
&& !hasAnyBlocksBetweenSafe(safe, data.to())
&& timeSinceLastCollision >= 1500;

if (safeToUpdate) {
// player.sendMessage("Updated");
data.setSafePhaseLocation(data.from());
}

return false;
}

Expand Down
33 changes: 18 additions & 15 deletions src/main/java/me/vrekt/arc/check/moving/Speed.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import cn.nukkit.block.BlockCobweb;
import cn.nukkit.level.Location;
import cn.nukkit.potion.Effect;
import cn.nukkit.utils.TextFormat;
import me.vrekt.arc.check.Check;
import me.vrekt.arc.check.CheckType;
import me.vrekt.arc.check.result.CheckResult;
Expand Down Expand Up @@ -74,9 +73,9 @@ public Speed() {
addConfigurationValue("block-ice-delta-min", 0.02);
addConfigurationValue("block-ice-delta-amount-max", 5);
addConfigurationValue("max-move-speed-stairs", 0.6);
addConfigurationValue("in-air-min-delta", 0.02);
addConfigurationValue("in-air-min-delta", 0.01);
addConfigurationValue("in-air-max-delta-amount", 10);
addConfigurationValue("max-in-air-speed", 0.50);
addConfigurationValue("max-in-air-speed", 0.62);
addConfigurationValue("max-in-air-ice-speed", 0.56);
addConfigurationValue("max-in-air-slimeblock-speed", 0.45);

Expand All @@ -90,7 +89,7 @@ public Speed() {
* @param data their data
*/
public void check(Player player, MovingData data) {
if (exempt(player) || exempt(player, ExemptionType.TELEPORT)) return;
if (exempt(player) || exempt(player, ExemptionType.TELEPORT) || player.riding != null) return;
startTiming(player);

if (data.getSafeSpeedLocation() == null) {
Expand Down Expand Up @@ -140,16 +139,21 @@ private void runAirChecks(Player player, MovingData data, CheckResult result, Lo
// check if the player is moving too similar over time
final double delta = Math.abs(data.getLastHorizontal() - horizontal);
if (delta <= inAirMinDelta) {
final int count = data.getInAirDeltaAmount() + 1;
data.setInAirDeltaAmount(count);

if (count > inAirMaxDeltaAmount) {
result.setFailed("Moving too similar in-air")
.withParameter("delta", delta)
.withParameter("min", inAirMinDelta)
.withParameter("count", count)
.withParameter("max", inAirMaxDeltaAmount);
handleCheckViolationAndReset(player, result, setback);
// ignore cases where we are super far from ground.
// TODO: This can cause bypasses.
final double distance = MathUtil.distance(data.ground(), data.to());
if (distance <= 2.8) {
final int count = data.getInAirDeltaAmount() + 1;
data.setInAirDeltaAmount(count);

if (count > inAirMaxDeltaAmount) {
result.setFailed("Moving too similar in-air")
.withParameter("delta", delta)
.withParameter("min", inAirMinDelta)
.withParameter("count", count)
.withParameter("max", inAirMaxDeltaAmount);
handleCheckViolationAndReset(player, result, setback);
}
}
} else {
data.setInAirDeltaAmount(0);
Expand Down Expand Up @@ -230,7 +234,6 @@ private void runGroundChecks(Player player, MovingData data, CheckResult result,
// regular flag.
// ensure player has had no ice recently.
if (data.offIceTime() >= 10 && data.getOffModifierTime() >= 10) {
player.sendMessage(TextFormat.YELLOW + "REGULAR FLAG");
result.setFailed("Moving too fast")
.withParameter("h", horizontal)
.withParameter("max", base)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@
import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.command.CommandSender;
import cn.nukkit.utils.TextFormat;
import me.vrekt.arc.Arc;
import me.vrekt.arc.check.CheckType;
import me.vrekt.arc.permissions.Permissions;
import me.vrekt.arc.utility.chat.ColoredChat;
import me.vrekt.arc.violation.ViolationHistory;
import org.apache.commons.lang3.ArrayUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
* Allows you to view a summary about a player.
Expand Down Expand Up @@ -39,9 +45,42 @@ public void execute(CommandSender sender, String[] arguments) {
final int gameMode = player.getGamemode();
final boolean op = player.isOp();

final List<CheckType> bypass = Permissions.getChecksCanBypass(player);
final String header = "";
final List<String> bypass = Permissions.getChecksCanBypass(player)
.stream().map(CheckType::getName)
.collect(Collectors.toList());
final ColoredChat message = ColoredChat.forRecipient(sender);

sender.sendMessage(header);
final int playerDevice = player.getLoginChainData().getDeviceOS();
final int playerPing = player.getPing();

final String playerDeviceId = playerDevice == 7 ? "Windows" : "Unknown";
final String checksBypassed = bypass.isEmpty() ? " cannot bypass any checks."
: " can bypass " + ArrayUtils.toString(bypass);
final String playerGameMode = player.getGamemode() == 0 ? "Survival"
: player.getGamemode() == 1 ? "Creative"
: player.getGamemode() == 2 ? "Adventure"
: player.getGamemode() == 3 ? "Spectator"
: "Survival";

message.setMainColor(TextFormat.AQUA).setParameterColor(TextFormat.GOLD);
message.messagePrefix("Viewing summary report for: ").parameter(player.getName()).newLine();
message.parameterPrefix(player.getName()).message(" is playing on ").parameter(playerDeviceId).newLine();
message.parameterPrefix(player.getName()).message(" is currently in ").parameter(playerGameMode).newLine();
message.parameterPrefix(player.getName()).message(checksBypassed).newLine();
message.messagePrefix("The ping of ").parameter(player.getName()).message(" is ").parameter(playerPing + " ms.").newLine();

final ViolationHistory history = Arc.getInstance().getViolationManager().getHistory().get(player.getUniqueId());
if (history != null) {
history.getViolations().forEach((check, level) -> {
message.parameterPrefix(player.getName())
.message(" failed ")
.parameter(check.getName())
.parameter(" " + level)
.message(" times.")
.newLine();
});
}

message.send();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import cn.nukkit.level.Location;
import cn.nukkit.network.protocol.MovePlayerPacket;
import me.vrekt.arc.Arc;
import me.vrekt.arc.check.CheckCategory;
import me.vrekt.arc.check.CheckType;
import me.vrekt.arc.check.moving.Flight;
import me.vrekt.arc.check.moving.Phase;
import me.vrekt.arc.check.moving.Speed;
import me.vrekt.arc.data.moving.MovingData;
import me.vrekt.arc.listener.packet.NukkitPacketHandler;
import me.vrekt.arc.listener.packet.NukkitPacketListener;
import me.vrekt.arc.permissions.Permissions;
import me.vrekt.arc.utility.MovingAccess;

/**
Expand All @@ -36,7 +38,6 @@ public final class MovePlayerPacketListener extends NukkitPacketListener {

public MovePlayerPacketListener(NukkitPacketHandler handler) {
super(handler);

flight = Arc.getInstance().getCheckManager().getCheck(CheckType.FLIGHT);
speed = Arc.getInstance().getCheckManager().getCheck(CheckType.SPEED);
phase = Arc.getInstance().getCheckManager().getCheck(CheckType.PHASE);
Expand All @@ -45,6 +46,7 @@ public MovePlayerPacketListener(NukkitPacketHandler handler) {
@Override
public void onPacketReceiving(DataPacketReceiveEvent event) {
final Player player = event.getPlayer();
if (Permissions.canBypassCategory(player, CheckCategory.MOVING)) return;

final MovingData data = MovingData.get(player);
final MovePlayerPacket packet = (MovePlayerPacket) event.getPacket();
Expand All @@ -59,7 +61,7 @@ public void onPacketReceiving(DataPacketReceiveEvent event) {
MovingAccess.calculateMovement(player, data, from, to);
if (flight.enabled()) flight.check(player, data);
if (speed.enabled()) speed.check(player, data);
// if (phase.enabled()) phase.check(player, data);
// if (phase.enabled()) phase.check(player, data);
}
}

Expand Down
47 changes: 47 additions & 0 deletions src/main/java/me/vrekt/arc/utility/block/ray/RayTrace.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package me.vrekt.arc.utility.block.ray;

import cn.nukkit.level.Level;
import cn.nukkit.level.Location;
import cn.nukkit.math.AxisAlignedBB;

/**
* Represents a ray tracer.
*/
public interface RayTrace {

/**
* Set where to ray-trace.
*
* @param from the starting location
* @param to the end location
* @param bb the player bounding box.
*/
void set(Location from, Location to, AxisAlignedBB bb);

/**
* Loop through all blocks defined within the start and end position.
*/
void loop();

/**
* Step through the next block, returning {@code true} if there is a collision.
*
* @param level the level
* @param blockX the block X
* @param blockY the block Y
* @param blockZ the block Z
* @param minX minimum X
* @param minY minimum Y
* @param minZ minimum Z
* @param maxX maximum X
* @param maxY maximum Y
* @param maxZ maximum Z
* @return {@code true} if any collision occurs.
*/
boolean step(Level level, final int blockX, final int blockY, final int blockZ,
final double minX, final double minY, final double minZ,
final double maxX, final double maxY, final double maxZ);

boolean collides();

}
10 changes: 10 additions & 0 deletions src/main/java/me/vrekt/arc/utility/chat/ColoredChat.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ public ColoredChat parameter(String parameter) {
return this;
}

/**
* Append a new line
*
* @return this
*/
public ColoredChat newLine() {
builder.append("\n");
return this;
}

/**
* Append a parameter
*
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/me/vrekt/arc/violation/ViolationHistory.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,39 @@ public final class ViolationHistory {
*/
private final Map<CheckType, Integer> violations = new HashMap<>();

/**
* The time when this history was created
*/
private long timeCreated;

public ViolationHistory() {
timeCreated = System.currentTimeMillis();
}

/**
* @return get the time created
*/
public long getTimeCreated() {
return timeCreated;
}

/**
* Set the time created.
* Also used for reset.
*
* @param timeCreated the time created
*/
public void setTimeCreated(long timeCreated) {
this.timeCreated = timeCreated;
}

/**
* Clear.
*/
public void clear() {
violations.clear();
}

/**
* Get the violation level for a check
*
Expand Down
Loading

0 comments on commit 4ead29d

Please sign in to comment.