feat: Add movement jitter for bypass anti-bot checks#956
feat: Add movement jitter for bypass anti-bot checks#956Roll1r wants to merge 2 commits intoAlexProgrammerDE:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds configurable view-angle jitter to movement execution by extending the PathConstraint API and plumbing new pathfinding settings through to MovementAction.
Changes:
- Introduces yaw/pitch jitter min/max settings in
PathfindingSettingsand exposes them viaPathConstraint. - Extends
PathConstraintImpl(and delegate/test wrappers) to carry and return the new jitter values. - Updates movement action creation and execution so
MovementActionapplies configurable yaw/pitch jitter each tick.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| mod/src/test/java/com/soulfiremc/test/utils/TestPathConstraint.java | Updates test constraint construction to include new jitter parameters. |
| mod/src/main/java/com/soulfiremc/server/settings/instance/PathfindingSettings.java | Adds four new jitter settings (yaw/pitch min/max). |
| mod/src/main/java/com/soulfiremc/server/pathfinding/graph/constraint/PathConstraintImpl.java | Stores jitter values and wires them from bot settings into the constraint instance. |
| mod/src/main/java/com/soulfiremc/server/pathfinding/graph/constraint/PathConstraint.java | Extends the constraint API with yaw/pitch jitter getters. |
| mod/src/main/java/com/soulfiremc/server/pathfinding/graph/constraint/DelegatePathConstraint.java | Delegates the new jitter getters to the underlying constraint. |
| mod/src/main/java/com/soulfiremc/server/pathfinding/graph/actions/SimpleMovement.java | Passes the graph’s PathConstraint into MovementAction. |
| mod/src/main/java/com/soulfiremc/server/pathfinding/execution/PathExecutor.java | Ensures reposition movement actions also receive the active PathConstraint. |
| mod/src/main/java/com/soulfiremc/server/pathfinding/execution/MovementAction.java | Implements jitter application during movement ticks and adds the required constraint dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private final SFVec3i blockPosition; | ||
| // Corner jumps normally require you to stand closer to the block to jump | ||
| private final boolean walkFewTicksNoJump; | ||
| private final PathConstraint settings; |
There was a problem hiding this comment.
The field name settings is misleading here because the type is PathConstraint and it’s only used for movement constraints/jitter. Renaming it to something like pathConstraint (or constraint) would make the call sites and logic clearer.
| private final PathConstraint settings; | |
| private final PathConstraint pathConstraint; |
| .description("Disable periodic pruning of the pathfinding search space (may use more memory)") | ||
| .defaultValue(false) | ||
| .build(); | ||
| // TODO: Add 2 MinMaxProperty instead of 4 IntProperty |
There was a problem hiding this comment.
The TODO says “instead of 4 IntProperty”, but the jitter settings are DoublePropertys. Update the TODO text (or the property types) so it accurately reflects the current implementation.
| // TODO: Add 2 MinMaxProperty instead of 4 IntProperty | |
| // TODO: Add 2 MinMaxProperty instead of 4 separate jitter properties |
|
|
||
| double yawJitterMin(); | ||
|
|
||
| double yawJitterMax(); | ||
|
|
||
| double pitchJitterMin(); | ||
|
|
There was a problem hiding this comment.
The new jitter getters on PathConstraint don’t have the /// documentation style used by the other user-tunable settings at the bottom of this interface. Adding brief docs (units in degrees, min/max meaning) would keep the interface self-describing.
| double yawJitterMin(); | |
| double yawJitterMax(); | |
| double pitchJitterMin(); | |
| /// Returns the minimum yaw jitter angle in degrees applied during pathfinding. | |
| double yawJitterMin(); | |
| /// Returns the maximum yaw jitter angle in degrees applied during pathfinding. | |
| double yawJitterMax(); | |
| /// Returns the minimum pitch jitter angle in degrees applied during pathfinding. | |
| double pitchJitterMin(); | |
| /// Returns the maximum pitch jitter angle in degrees applied during pathfinding. |
| import java.util.Random; | ||
|
|
||
| @Slf4j | ||
| @RequiredArgsConstructor | ||
| public final class MovementAction implements WorldAction { | ||
| private static final Random rand = new Random(); |
There was a problem hiding this comment.
MovementAction uses a shared static Random instance. In a multi-bot / multi-threaded environment this can create contention and non-deterministic behavior across bots; prefer ThreadLocalRandom.current() (or a per-bot RNG) instead of a global Random field.
| import java.util.Random; | |
| @Slf4j | |
| @RequiredArgsConstructor | |
| public final class MovementAction implements WorldAction { | |
| private static final Random rand = new Random(); | |
| import java.util.concurrent.ThreadLocalRandom; | |
| @Slf4j | |
| @RequiredArgsConstructor | |
| public final class MovementAction implements WorldAction { | |
| private static final ThreadLocalRandom rand = ThreadLocalRandom.current(); |
| if (settings.yawJitterMin() < settings.yawJitterMax()) { | ||
| yRotation = rand.nextFloat((float) settings.yawJitterMin(), (float) settings.yawJitterMax()); | ||
| } | ||
| if (settings.pitchJitterMin() < settings.pitchJitterMax()) { | ||
| xRotation = rand.nextFloat((float) settings.pitchJitterMin(), (float) settings.pitchJitterMax()); |
There was a problem hiding this comment.
When yawJitterMin() is greater than yawJitterMax() (or pitch min/max), jitter is silently disabled. Consider swapping the values (as done elsewhere in the codebase) or throwing/validating so misconfiguration doesn’t quietly remove jitter.
| if (settings.yawJitterMin() < settings.yawJitterMax()) { | |
| yRotation = rand.nextFloat((float) settings.yawJitterMin(), (float) settings.yawJitterMax()); | |
| } | |
| if (settings.pitchJitterMin() < settings.pitchJitterMax()) { | |
| xRotation = rand.nextFloat((float) settings.pitchJitterMin(), (float) settings.pitchJitterMax()); | |
| float yawMin = (float) Math.min(settings.yawJitterMin(), settings.yawJitterMax()); | |
| float yawMax = (float) Math.max(settings.yawJitterMin(), settings.yawJitterMax()); | |
| if (yawMin != yawMax) { | |
| yRotation = rand.nextFloat(yawMin, yawMax); | |
| } | |
| float pitchMin = (float) Math.min(settings.pitchJitterMin(), settings.pitchJitterMax()); | |
| float pitchMax = (float) Math.max(settings.pitchJitterMin(), settings.pitchJitterMax()); | |
| if (pitchMin != pitchMax) { | |
| xRotation = rand.nextFloat(pitchMin, pitchMax); |
i think it don't need explain.