Repository navigation
Conversation
nativeGamepadButtonEvent's third argument is the button's value, not KeyEvent's action: 1 is held, 0 is released. The engine stores it as the event's value and its input pipeline reads a non-zero value as held. Cordial sent the action, so every button registered on its release and stayed held until its next press. A game that reads a held jump button -- a mobile jump control, which is what the Android client draws -- repeats the jump for as long as the button is held, so one A press left the character jumping without end. That is luohoa97#113's "the buttons start pressing on their own", and the 8BitDo report behind it. Measured on engine 2.741.0.1061 (the flag at 0x7334cb0 reads 0, so the legacy path runs): with the Roblox in-game menu open, a lone action=0 left the menu untouched and a lone action=1 toggled it, twice over, for B and for Start. On the patched build the menu opens on the press and the in-game Token shop opens on the press, and a real 8BitDo in Bee Swarm produced 24 balanced events, every press action=0 value=1 and every release action=1 value=0. The conversion lives in deliver_gamepad_button, the single delivery point, so callers keep speaking Android's action and devctl padbutton keeps taking down|up. The legacy path also derives a 2*isDown flag from the argument, which this inverts; nothing observable follows that flag, and path A (flag on) uses only the value, so the value is the contract in both.
A pad that is unplugged, or a joydev node that disappears, left the engine believing every button it had down was still down. An unplug gets its releases from the kernel, which emits one per held key when a device is destroyed (measured: A held on a destroyed uinput pad arrives as key=96, action=1, before ENODEV). Switching controllers off in Settings only closes the file, and then nothing sends the release at all: the engine keeps the button pressed for the rest of the run, which in a game reads as the button pressing itself long after it was let go. Track the buttons each pad is holding in a bitmask (Pad.held) and, on withdraw, send one release per named button before the disconnect. The mask follows the event that was actually sent, so a button the layout cannot name is never released later either. Indices past 31 are not tracked; no pad here declares more than sixteen buttons. A pad opened under a finger is also out of step, in the other direction: its init burst is the pad's current state, and the pressed records in it were dropped with the rest of the burst. Replay the ones that are down after the announcement, and only those -- every pad opens with most buttons up, and eleven no-op releases per plug-in are noise in the trace, not information. Axes are left out on purpose: a stick that is already off centre corrects itself on its next event, and a trigger at rest reads full-scale on some pads. Four unit tests: the mask follows press and release, release_held sends one up per named button and clears, a button held at withdraw is released before the disconnect, and an init burst replays only the buttons that are down.
This branch has not been deployed
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.
Press A once with a gamepad in a Roblox game and the character jumps forever; B, X and Y behave the same way. That is what #113 describes ("the buttons start pressing on their own"), and I could reproduce it with an 8BitDo in Bee Swarm.
The cause is the third argument to
nativeGamepadButtonEvent. It is the button's value - 1 while held, 0 once released - not Android'sKeyEventaction, which is what Cordial was sending. The engine keeps the argument as the event's value and its input pipeline reads a non-zero value as held, so every button registered on its release and then stayed held until its next press. A mobile jump button repeats while it is held, which is why the character never comes down.How I got there: on engine 2.741.0.1061 (the flag at 0x7334cb0 reads 0, so the legacy path runs) I opened the Roblox in-game menu and sent a lone
action=0, which did nothing, and then a loneaction=1, which toggled the menu. Same result twice, for B and for Start. With the conversion in place the menu opens on the press instead, the in-game Token shop opens on the press, and a real 8BitDo in Bee Swarm produced 24 balanced events - every pressaction=0 value=1, every releaseaction=1 value=0.The conversion sits in
deliver_gamepad_button, the one place buttons are delivered, so callers keep speaking Android's action anddevctl padbuttonkeeps takingdown|up. A unit test pins it.One caveat: the legacy path also derives a
2*isDownflag from the argument, and this inverts that. Nothing observable follows the flag, and path A (flag on) uses only the value, so I treat the value as the contract in both. I only measured one engine build.The second commit is independent and can be dropped: it tracks which buttons a pad is holding and releases them when Cordial drops the pad, and replays the pressed records of a pad's init burst. Without it, switching controllers off in Settings leaves the engine believing the buttons are still down, which reads as the same bug.