Input
Input is built with the window. It installs GLFW callbacks for the cursor, keys, mouse buttons,
characters, and focus. Gameplay code reads it through world.getInput(). You do not poll OS
devices yourself.
The ring and the poll
Two records exist on purpose.
| Record | When it is written | What you use it for |
|---|---|---|
| Rust input ring | Inside the callback, stamped with nowNs() |
The 1 ms body step. A press that lasts one millisecond only affects that step. |
| Java edges | beginFrame(), once after pollEvents |
wasTabPressed, wasEscapePressed, chat keys, clicks for UI. |
isKeyDown(int) asks GLFW whether the key is down now. It is the right call for βis sprint held
this gameplay tick.β It is not a history. The ring is the history.
Key auto-repeat is ignored. A press and a release are the samples. Mouse motion larger than 40 pixels on one
axis is dropped, which rejects a focus glitch. consumeLookDelta then applies a 0.15 pixel
deadzone and returns the sum for this frame. Call it once. A second call in the same frame reads zeros.
Look
If handlesLookInput() is false, the loop calls camera.turn(dx, dy). Sensitivity and
invert live on the camera. If the world handles look, applyFrameLook receives the same summed
delta. OptiShoot uses that to orbit the third-person camera and to counter weapon recoil.
setLookActive(false) releases the cursor and suppresses look deltas. Menus do this.
setTextCapture(true) does the same and queues typed characters for chat.
drainChars empties that queue into a StringBuilder.
Bindings
InputMap maps GameAction values to GLFW key codes. Defaults are WASD, space, left
shift, left control, E for inventory, and the number row for the hotbar. Persist them as key_*
entries in settings.ini. isDown(input, action) is the check gameplay should call,
not a hardcoded GLFW_KEY_W.
GameAction.PERSPECTIVE is the view cycle: first person, third-person back, third-person front.
Fire and aim are mouse buttons. The map stores -1 for those. Input.wasLeftClicked
and isMouseButtonDown cover them.
When the character sim is enabled, publishToSim copies the current bindings into Rust. Rebinding
in the pause menu takes effect on the next frame, because publish runs every frame.
Cursor for UI
getCursorFramebuffer writes the cursor in framebuffer pixels, scaled for a retina window. UI hit
testing uses that, not the raw GLFW cursor, which is in window coordinates.