Skip to content

fix: stop freecam from sinking when toggle sneak is enabled - #599

Open
reusteur73 wants to merge 2 commits into
MinecraftFreecam:mainfrom
reusteur73:main
Open

reusteur73 wants to merge 2 commits into
MinecraftFreecam:mainfrom
reusteur73:main

Conversation

@reusteur73

Copy link
Copy Markdown

When Toggle Sneak is enabled (Options > Controls), the sneak
keybind becomes a toggle instead of a hold. Freecam's descend movement reads
that key's isDown() directly, so if sneak happened to be toggled on, the
camera would just sink forever with no way to stop it besides pressing sneak
again which also toggled the real player's crouch or by pressing jump key.

This makes freecam poll the sneak key's actual physical state instead,
independent of the toggle setting. Descending now works like holding jump to
ascend: only active while the key is actually held down.

Tested on Fabric 26.2. Compiles fine on the other supported versions too
(1.17.1 through 26.1, NeoForge 26.2), but I didn't run those in-game.

@MattSturgeon MattSturgeon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix!

1.4.1 is currently on release candidate, so I'll land this after 1.4.1 has released.

In the mean time, could you switch from an Accessor Mixin to an Access Widener entry and add a change file to .changeset?

(also re #598, you don't need to close/open new PRs. It's perfectly fine to force-push to the existing PR)

(also, I've been doing some CI changes today, so you'll need to rebase on our latest main to run the correct 'required checks')

Comment thread common/src/main/java/net/xolt/freecam/mixins/KeyMappingAccessor.java Outdated
Comment thread common/src/main/java/net/xolt/freecam/util/Motion.java
@MattSturgeon

Copy link
Copy Markdown
Member

I took a few minutes to address my earlier feedback, so next time you work on this you'll need to overwrite your local branch with what I force-pushed to your GitHub fork.

Details

git stash
git fetch --all
git reset --hard @{u}
git stash pop

Note: git reset --hard reset what you have locally to what I pushed to your remote. That's probably what you want, unless you have made some changes locally that you didn't push and don't want to lose them.

Only run git stash and git stash pop if you have uncommitted changes you wish to re-apply after resetting to what I pushed.


I noticed in testing that using the sneak key while in freecam will cause toggle-sneak to togglne upon exiting freecam. Ideally, we'd fix that too.

@github-actions github-actions Bot added the release Pull requests that have an unpublished release label Aug 31, 2026
@reusteur73

reusteur73 commented Aug 31, 2026

Copy link
Copy Markdown
Author

Thanks for the feedback, I hadn't noticed that bug. I tried to implement a fix in 2cdef7a and it seems to work properly. Let me know if you need further changes.

@MattSturgeon

MattSturgeon commented Aug 31, 2026

Copy link
Copy Markdown
Member

The current CI failures are due to a maven repo being down: https://status.trans.fish/status/kiku (I'll trigger a re-run later).

Looking at the diff you pushed up, that should work. Tracking state is never my preferred option, though. Perhaps it's possible for a mixin to prevent the key event propagating to the toggle-sneak binding while Freecam.isEnabled(), or something along those lines?

If that proves too messy or too fragile, the current solution should be ok.

@MattSturgeon MattSturgeon added the bug Something isn't working label Aug 31, 2026
@github-actions github-actions Bot removed the release Pull requests that have an unpublished release label Aug 31, 2026

@MattSturgeon MattSturgeon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My instinct is that there's a cleaner approach than storing/restoring remembered initial sneak state, likely involving a mixin.

I suspect we'll also need to give some consideration to the "freecam is active, but in 'control player' mode" scenario.

private static TripodSlot activeTripod = TripodSlot.NONE;
private static FreeCamera freeCamera;
private static CameraType rememberedF5 = null;
private static boolean sneakStateOnEnable = false;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit(style): Not super important, but maybe we should use the same style as rememberedF5:

Suggested change
private static boolean sneakStateOnEnable = false;
private static boolean rememberedSneakState = false;

Also: is there any value in making it nullable? I don't think it is possible to get into a situation where we disable freecam before the remembered state has been populated.

private static Boolean rememberedSneakState = null;

private static void onEnable() {
MC.smartCull = false;
outlineEnabled = ModConfig.get().shouldOutlinePlayer();
sneakStateOnEnable = MC.options.keyShift.isDown();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If going down the "store state" approach, I think we'll also have to update it if the state changes during "control player" mode; Freecam has an option to toggle control of the player vs the camera while freecam is active.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants