Skip to content

Add a Hitboxes mod with per-entity toggles and colors - #26

Merged
dsnsgithub merged 5 commits into
mainfrom
cursor/hitboxes-mod-dd32
Aug 31, 2026
Merged

Add a Hitboxes mod with per-entity toggles and colors#26
dsnsgithub merged 5 commits into
mainfrom
cursor/hitboxes-mod-dd32

Conversation

@dsnsgithub

Copy link
Copy Markdown
Owner

Adds a Hitboxes module to the Mods tab so collision boxes can be shown without F3+B, with independent visibility and color for each entity group.

Settings

  • Master enable (plus an unbound Toggle Hitboxes keybind)
  • Line width, look vector, eye-height line, and invisible entities
  • Per-type Show + Color for:
    • Players
    • Self
    • Arrows
    • Projectiles (pearls, snowballs, eggs, potions, fireballs, fishing bobbers)
    • Items
    • Hostile mobs
    • Passive mobs
    • Other (TNT, XP orbs, armor stands, vehicles, …)

Vanilla F3+B hitboxes are left alone when the module is off.

Usage

Open the client menu with Right Shift, enable Hitboxes under Mods, then toggle types and pick colors.

Open in Web Open in Cursor 

Render entity collision boxes independently of F3+B, with separate
show/color settings for players, self, arrows, projectiles, items,
hostile mobs, passive mobs, and other entities.

Co-authored-by: Dominic Seung <dominic@seung.dev>
@dsnsgithub
dsnsgithub marked this pull request as ready for review August 28, 2026 06:43
claude added 3 commits August 28, 2026 06:58
The three new Hitboxes files carried a single DSNS copyright line with
the fork wording, matching none of the configured header rules:
HEADER_NEW rejected "part of DolphinClient, a fork of AxolotlClient",
while HEADER_FORK and HEADER expect a second copyright line. These are
original files, so use HEADER_NEW verbatim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmYtYPapkLEw3N96pZf7Pv
The @WrapOperation on Entity.isInvisible used field-target syntax for a
method target ("isInvisible:()Z"), which is how javap prints a constant
pool entry but not what Mixin's @at accepts. Mixin rejected it with
"Invalid name: isInvisible:", EntityRenderDispatcher failed to transform,
and the client died before reaching the main menu.

Drop the colon so the target parses as a method. The colon is still
correct on the renderHitboxes FIELD target directly above.

Verified by running the 1.8.9 client: it now boots with no mixin errors,
the Hitboxes category renders under Rendering, and hitboxes draw in world
with the per-type colours (self cyan, passive green, hostile dark red,
items yellow) plus the eye-height and look-vector lines.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmYtYPapkLEw3N96pZf7Pv
Four panels from a real 1.8.9 client run: the Hitboxes config section
(global options and the per-type Show/Colour groups) and the hitboxes
rendering in world with the per-type colours.

This is a PR attachment rather than shipped content -- drop it before
merge if the repo would rather not carry screenshots.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmYtYPapkLEw3N96pZf7Pv

Copy link
Copy Markdown
Owner Author

Fixed: the mod crashed the game on startup

The Hitboxes module never ran — the client died before the main menu, so nothing in this PR could work.

EntityRenderDispatcherMixin targeted Entity.isInvisible with field-target syntax for a method target:

target = "Lnet/minecraft/entity/Entity;isInvisible:()Z"   // note the colon

That colon is how javap prints a constant-pool entry, but it is not what Mixin's @At accepts. Mixin rejected it, EntityRenderDispatcher failed to transform, and the whole client went down:

InvalidMemberDescriptorException: Invalid name: isInvisible:
Failed validating @At("INVOKE").target "Lnet/minecraft/entity/Entity;isInvisible:()Z"
Mixin apply for mod dolphinclient failed ... FAILED during APPLY

Fix is dropping the colon (466a72b). The colon is still correct on the renderHitboxes FIELD target on the line above — that one was always fine.

CI never surfaced this because the build failed at checkLicenseMain before :1.8.9:compileJava ever ran. That license failure is fixed in b15247f.

Verified by actually running it

Booted the 1.8.9 client (Xvfb + Mesa llvmpipe): no mixin errors, module loads, config renders, hitboxes draw.

Hitboxes config and in-game rendering

Top row — the config section under Mods → Rendering → Hitboxes: line width, look vector, eye-height line, invisible entities, then the per-type Show + Colour groups (Self cyan, Players white).

Bottom row — hitboxes rendering in world. Sampling the framebuffer confirms the per-type colours are actually distinct and correctly assigned:

Group Colour Pixels found
Self #00FFFF cyan 868
Passive mobs (cow, pig) #55FF55 green 271
Hostile mobs (spider, creeper) #AA0000 dark red 551
Items (dropped porkchop/beef) #FFFF55 yellow confirmed separately
Eye-height line red 359
Look vector blue 200

Classification is correct including the case that first looked wrong to me: animals that died on a fall were drawn yellow because they had become dropped-item entities, which is the intended ITEMS grouping.

./gradlew build passes locally — license checks, compile, tests, remapJar.

Two notes, neither blocking

  1. I could not find the master enable toggle anywhere in the config UI. Options named enabled are not rendered inline for categories nested under Rendering, so the module can only be switched on via the unbound Toggle Hitboxes keybind or by editing the config. This is not specific to this PR — Motion Blur, Menu Blur and Scrollable Tooltips use the identical category.add(enabled, …) + rendering.add(category) pattern and behave the same, so I left it alone. Worth binding a key by default if you want it reachable out of the box.
  2. The PR description says the module lands "in the Mods tab"; it actually lands under Mods → Rendering, since the category is added to config().rendering.

The screenshot is committed at docs/hitboxes.png purely so it renders here — the API has no way to attach an image to a comment. Drop that commit before merge if you'd rather not carry screenshots in the repo.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

The image link in my previous comment was wrong — I used an incorrect commit SHA, so it 404s. Correct one:

Hitboxes config and in-game rendering

Top row — the config under Mods → Rendering → Hitboxes: line width, look vector, eye-height line, invisible entities, then the per-type Show + Colour groups (Self cyan, Players white).

Bottom row — hitboxes rendering in world after the mixin fix: cyan self box, green cow/pig, dark-red spider/creeper, red eye-height line, blue look vector.

Everything else in that comment stands.


Generated by Claude Code

@dsnsgithub
dsnsgithub marked this pull request as draft August 28, 2026 07:52
Hitboxes was nested under the rendering category, which put it inside the
Rendering tile on the Mods tab. That also hid its master enable: the menu
catalog filters out options named "enabled" and only re-surfaces them as a
tile-level toggle, so a category rendered as a nested section loses its
switch entirely. The module could only be turned on by binding the unbound
keybind or editing the config by hand.

Register the category at the config root and route it to the HUD tab, the
same way "general" is routed to Settings. Tiles on the HUD tab now keep
their children as sections rather than promoting each one, otherwise the
eight per-entity groups would each become a separate tile.

Hitboxes is now its own HUD tile with a working enable toggle, and the
per-type Show/Colour groups render inside it as sections.

Note this moves the saved options from rendering.hitboxes to a top-level
hitboxes block, so existing values reset to defaults.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XmYtYPapkLEw3N96pZf7Pv

Copy link
Copy Markdown
Owner Author

Moved Hitboxes from Rendering to the HUD tab (707cee0)

This also fixes the missing master enable I flagged earlier — same root cause.

MenuCatalog filters out options named enabled from the option list and only re-surfaces them as a tile-level toggle. rendering has more than 12 children, so shouldPromote collapses it into a single "Rendering" tile and renders each child as an inline section — and sections don't get a toggle. Nested under Rendering, Hitboxes could only be switched on via the unbound keybind or by hand-editing the config.

Two changes:

  • Hitboxes registers its category at the config root (config().addCategory) instead of config().rendering.
  • MenuCatalog routes hitboxes to Tab.HUD, mirroring how general is routed to Tab.SETTINGS. shouldPromote now returns false for Tab.HUD, so the tile keeps its children as sections — without that, the eight per-entity groups would each become their own tile.

Note the HUD tab couldn't host it directly: it's built from HudManager.getEntries() plus nodesFrom(hudCategory, true), and that true skips subcategories, so a plain category added to hudCategory is silently dropped.

Hitboxes on the HUD tab

Verified on a real client run: Hitboxes is its own HUD tile with a working toggle, the per-type Show/Colour groups render inside it as sections, and enabling it purely through the UI (no config editing) draws the hitboxes — self cyan, passive green, hostile dark red, plus eye-height and look-vector lines. ./gradlew build passes.

⚠️ This moves saved options from rendering.hitboxes to a top-level hitboxes block, so any existing values reset to defaults.

The PR description still says the module lands "in the Mods tab" — that's now the HUD tab. I left the description alone rather than editing your text.


Generated by Claude Code

@dsnsgithub
dsnsgithub marked this pull request as ready for review August 31, 2026 01:00
@dsnsgithub
dsnsgithub merged commit ef16420 into main Aug 31, 2026
1 check 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.

3 participants