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.

RecordWhen it is writtenWhat 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.