Fix action binding device lookup (pause / reset VR binding not working)#160
Open
chrisraff wants to merge 1 commit into
Open
Fix action binding device lookup (pause / reset VR binding not working)#160chrisraff wants to merge 1 commit into
chrisraff wants to merge 1 commit into
Conversation
MemoryListener.Start() was looking up joysticks by raw positional index
(ElementAtOrDefault(joySlot)) into a fresh DirectInput scan. The JOY slot
values in controls.ini are written based on the device enumeration order at
save time, but the MemoryListener's scan happens later—after AC has started
and potentially after the background DirectInputScanner has refreshed
_staticData with a new enumeration order.
AC itself identifies devices by GUID via the [CONTROLLERS] __IGUID entries,
so it's immune to enumeration order changes. The MemoryListener was not,
causing non-gameplay action bindings (pause, start race, reset VR, etc.) to
silently map to the wrong or missing joystick on repeated launches.
Fix: read __IGUID{slot} from controls.ini [CONTROLLERS] in the constructor,
then in Start() resolve each JOY slot to a joystick by matching instance GUID
rather than by position. Falls back to positional lookup for older configs
that lack __IGUID entries.
Also tighten the usedJoysticks filter from `x.Joystick != null` (always true,
since JoystickHolder is always constructed) to `x.Joystick.Device != null`,
so slots that resolve to no device are excluded upfront.
https://claude.ai/code/session_01WpWqqEVanpbdUffLwYd3tV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR fixes a bug where non-gameplay action bindings (start race, pause, reset VR, menu navigation) would stop working on subsequent launches. In my experience, repeated launches would cause wheel and button box inputs to stop registering for these actions.
I have limited experience with C#, especially for this large of a project, so I used Claude to help author the fix. I've reviewed the changes myself and validated the behavior through about a week of normal gameplay. Happy to dig into this further or work with contributors if any changes are needed.
AI summary of change:
MemoryListener.Start() was looking up joysticks by raw positional index (ElementAtOrDefault(joySlot)) into a fresh DirectInput scan. The JOY slot values in controls.ini are written based on the device enumeration order at save time, but the MemoryListener's scan happens later—after AC has started and potentially after the background DirectInputScanner has refreshed _staticData with a new enumeration order.
AC itself identifies devices by GUID via the [CONTROLLERS] __IGUID entries, so it's immune to enumeration order changes. The MemoryListener was not, causing non-gameplay action bindings (pause, start race, reset VR, etc.) to silently map to the wrong or missing joystick on repeated launches.
Fix: read __IGUID{slot} from controls.ini [CONTROLLERS] in the constructor, then in Start() resolve each JOY slot to a joystick by matching instance GUID rather than by position. Falls back to positional lookup for older configs that lack __IGUID entries.
Also tighten the usedJoysticks filter from
x.Joystick != null(always true, since JoystickHolder is always constructed) tox.Joystick.Device != null, so slots that resolve to no device are excluded upfront.