Skip to content

flyEnvelope: count hitbox edge support as ground (#35) - #41

Merged
ThoriaDevelopment merged 1 commit into
ThoriaDevelopment:mainfrom
Verslabs:fix/flyb-sneak-edge-footing
Oct 12, 2026
Merged

ThoriaDevelopment merged 1 commit into
ThoriaDevelopment:mainfrom
Verslabs:fix/flyb-sneak-edge-footing

Conversation

@Verslabs

@Verslabs Verslabs commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #35. groundedProxy only samples the block column under the hitbox centre. A player sneaking at a ledge (void edge, tower top) with the centre past the edge therefore reads as airborne while standing still. A level airborne tick falls in the Fly(FlyB) friction band every tick (dy=0, prevDeltaY=0 ⇒ dy − expectedY ≈ 0.078), so FlyB alerted within a few ticks.

Changes

  • FlyEnvelopeCheck: the grounded branch now also accepts a level tick (|dy| < 0.01) with a solid block within 0.05 under any column of the 0.6-wide hitbox footprint (isEdgeSupported). It only runs when the proxy already said airborne and the player is level. groundedProxy itself is unchanged, so other checks aren't affected.
  • New WorldQueries.isSolidBelowFootprint and the pure Footprint geometry helper (1, 2 or 4 distinct columns; centre first; a face that only touches a neighbouring column doesn't count; negative coordinates floor correctly).
  • New legit scenario legit-sneak-edge (sneaking on a 3-tall tower top with the centre 0.2 past the edge, 40 motionless ticks, then creeping along it). It asserts expectQuiet plus Fly(FlyB) / Fly(Blink) flag counts of 0. Before the fix: 57 Fly(FlyB) flags, peakVL 19.00 (an alert). After the fix: quiet.
  • FootprintTest unit tests for the column geometry.
  • scripts/checks.json fpGuards entry and docs/automated-live-testing.md coverage rows (FP-direction regressions 9 → 10).

Affected areas

  • Detection/check logic
  • Packet observation or inference
  • Config or presets
  • Commands or UI
  • Rendering or HUD
  • Replay, clips, camera, or input
  • Persistence or local data
  • Documentation/tests/tooling

Verification

Commands run (branch head 622c92b):

python scripts/verify_contribution.py --static
./gradlew test
./gradlew build
python scripts/live_selftest.py --check fly
python scripts/live_selftest.py --check sneak-edge
python scripts/live_selftest.py            # full three-pass run, see baseline note

Results:

  • Static verifier: PASS (only warning: no build/selftest-manifest.json before the first live run)
  • Tests: PASS, BUILD SUCCESSFUL, 54 tests, 0 failures, 0 errors (includes the new FootprintTest)
  • Build: PASS, BUILD SUCCESSFUL

Live client verification

  • Client launch/mixin application: PASS. The real 1.21.11 client booted through runClientGameTest, and pipeline-smoke passed.
  • Scenario(s): legit-sneak-edge (new), legit-fly-ramp, cheat-fly-hover-meteor, cheat-fly-ascend-liquidbounce, cheat-fly-strafehop-fusion, cheat-fly-antikick-itami, cheat-elytra-fly-liquidbounce
  • Expected result: the sneak-edge stance is quiet, and every fly cheat (including hover and antikick, which the edge-support concession could in principle hide) still alerts.
  • Observed result: --check fly 7/7 passed, --check sneak-edge 2/2 passed, legit false positives: none, cheat bypasses: none. In the full three-pass run, all 23 legit scenarios (including legit-sneak-edge) and all 10 replay scenarios passed (legit false positives: none). The 12 cheat-pass bypasses in that run are all among the 15 that main itself fails on this machine (see the baseline note below).
  • Not tested: no manual runClient session at a real void edge on a server.

Full-suite baseline on the test machine: the full python scripts/live_selftest.py run on main (5495a7f) on this machine (macOS, 8 GB RAM) also fails: 95 scenarios, 80 passed, 0 legit false positives, 15 cheat-pass bypasses in movement checks (flyEnvelope, noFallDamage, speedEnvelope, spider, noSlow, wallSprint, sprintHack, waterWalk, phaseClip). The same cheat scenarios pass when run on their own (e.g. cheat-speed-liquidbounce, cheat-fly-ascend-liquidbounce), so this looks like a resource/timing problem with the full run on a low-memory machine, not something this PR caused. The live evidence above therefore comes from targeted runs.

Safety and privacy review

  • No telemetry, uploads, analytics, or remote reporting were added.
  • No unintended outgoing gameplay packets were added.
  • Fail-open behavior is preserved where appropriate. (isEdgeSupported returns false, i.e. no exemption, on any error.)
  • Local-world, camera, input, and persistence state restore after stop/error/world change where relevant.
  • Logs, screenshots, clips, and test data contain no secrets or private information.

Documentation and migration

  • User-facing documentation updated, or no update is needed.
  • Config/clip migration reviewed, or no migration is needed.
  • Generated documentation source data updated if applicable. (scripts/checks.json fpGuards.)

AI assistance

  • AI tool(s) used: Claude Code (Claude Opus 5.5)
  • What the tool contributed: wrote the change, scenario and unit tests, and ran the static verifier, Gradle test/build and the live runs above.
  • What I reviewed manually: the diff, with an AI-assisted review pass on 2026-10-12. Maintainer review requested.

Known limitations and follow-up work

  • Same concession as groundedProxy: a flyer holding Δy ≈ 0 directly above any block the hitbox overlaps reads as grounded. The footprint widens that area from the centre column to the full 0.6 box.
  • Merge conflict with main: SelfTestEntrypoint.kt conflicts with checks: exempt creative/spectator flight from movement checks only #37 (creative/spectator scenarios). This branch needs a rebase before merge. The coverage counts in automated-live-testing.md should be rechecked after the rebase.

groundedProxy samples only the column under the hitbox center, so a
player sneaking at a ledge (void edge, tower top) with the center past
the edge reads as airborne while standing. A level airborne tick lands
in the FlyB friction band every tick (dy=0, prevDeltaY=0 =>
dy - expectedY ~= 0.078), which alerted within a few ticks.

FlyEnvelopeCheck's grounded branch now also accepts a level tick
(|dy| < 0.01) with a solid block within 0.05 under any column of the
0.6-wide footprint (WorldQueries.isSolidBelowFootprint, Footprint
geometry). groundedProxy itself is unchanged, so other checks are not
affected.

- new legit scenario legit-sneak-edge (pre-fix: 57 Fly(FlyB) flags,
  peakVL 19.00; post-fix: quiet)
- FootprintTest unit tests for the column geometry
- checks.json fpGuards + automated-live-testing.md coverage rows

AI assistance: Claude Code (Claude Opus 5.5) wrote the change and ran
the verification; needs human review.
@ThoriaDevelopment
ThoriaDevelopment force-pushed the fix/flyb-sneak-edge-footing branch from 622c92b to 51156d5 Compare October 12, 2026 18:32
@ThoriaDevelopment
ThoriaDevelopment merged commit 1baa781 into ThoriaDevelopment:main Oct 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Fly(FlyB) fires on sneaking at the void edge with half the hitbox over the void

2 participants