## [2.0.3] - 2026-04-04
### 🐛 Fixed
#### Critical — "Not Responding" on MC 1.21.11 (Root Cause)
- **DebugHudMixin crash on startup:** The `@Inject` in `DebugHudMixin` targeted the intermediary method name `method_1835` (getLeftText), which was remapped in MC 1.21.11. With the default `require=1`, a failed injection throws `InvalidInjectionException`, crashing the render thread and leaving a blank white "Not Responding" window. Fixed by adding `require=0` so the injection silently skips if the target method is not found in the current MC version.
- **`defaultRequire: 1` in mixin config:** `inputbooster.mixins.json` had `"defaultRequire": 1`, making every mixin injection fatal if unresolved. Changed to `"defaultRequire": 0` as a global safety net.
#### Thread Safety — Polling Thread Reading MC State Directly
- **Unsafe MC options reads from background thread (critical):** `InputPollingThread.poll()` was calling `MinecraftClient.getInstance()` and reading `mc.options.attackKey.isPressed()` and all other key bindings directly from the background polling thread. Minecraft's `KeyBinding` objects are not thread-safe — concurrent reads from a non-main thread cause lock contention and can deadlock the game. Introduced `KeySnapshot`, a new immutable class that captures all key states on the main thread once per tick. The polling thread now reads exclusively from this snapshot.
- **`WTapAssist` race condition:** `pendingWRelease` and `wReleaseTickDelay` were plain `boolean`/`int` fields written by the polling thread via `onWRelease()` and read by the main thread in `tick()`. Without `volatile`, the main thread could see stale values. Both fields marked `volatile`.
- **`CpsLimiter` not thread-safe:** `clickTimestamps` was an `ArrayDeque` — not safe for concurrent access. Replaced with `ConcurrentLinkedDeque`.
### ✨ Added
- **`KeySnapshot.java`** — New immutable class capturing all key binding states on the main thread each tick, published as a `volatile` field on `InputBoosterMod` for the polling thread to read safely. Eliminates all direct MC object access from the background thread.
### 🔧 Changed
- `InputPollingThread` no longer imports or references `MinecraftClient` or `GameOptions`.
- `InputBoosterMod` now updates `keySnapshot` each tick alongside `gameReady` and `gamePaused`.
- `DebugHudMixin` priority set to `900` and added null guard on `cir.getReturnValue()`.
Optional dependencies
Sodium
Any compatible version
Developer information
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle.
maven { name = "Modrinth"; url = "https://api.modrinth.com/maven" }