Skip to content
InputBooster
Developer DocumentationInternals

Architecture

How the InputBooster source tree is organised, from the loader entrypoints down to the drainer.

3 min readInputBooster 4.1.2-alphaMinecraft 26.2 / 26.3

The mod is a loader-neutral core with two thin platform entrypoints and one version-compat shim per Minecraft version. Everything else is shared.

The shape of the tree

Source layout
fabric/
src/
main/
java/
dev/
inputbooster/
platform/
InputBoosterFabric.java
src/
compat/
mc26_2/
java/
dev/
inputbooster/
compat/
McVersion.java
mc26_3/
java/
dev/
inputbooster/
compat/
McVersion.java
main/
java/
dev/
inputbooster/
access/
MixinAccess.java
engine/
CompatibilityManager.java
ConfigurationManager.java
DiagnosticsManager.java
InputEngine.java
InputEventDispatcher.java
KeyBindingProcessor.java
KeyboardProcessor.java
KeyStateManager.java
MouseProcessor.java
feature/
CpsLimiter.java
input/
KeyBindingSet.java
KeyboardRouter.java
RawKeyState.java
mixin/
GameTickMixin.java
screen/
InputBoosterScreen.java
ComboKeyPresets.java
InputAction.java
InputActionQueue.java
InputBoosterConfig.java
InputBoosterMod.java
InputDrainer.java
InputPollingThread.java
KeySnapshot.java
McCompat.java
neoforge/
java/
dev/
inputbooster/
platform/
InputBoosterNeoForge.java

The layers

The core path. The poller and the event mixins are the two sources; the drainer is the only place that touches the player.

The layers in detail

Platform entrypoints

Two files, each a few dozen lines:

FileLoaderWhat it does
InputBoosterNeoForge.javaNeoForgeCalls bootstrap(), registers the key mappings, forwards the client tick
InputBoosterFabric.javaFabricThe same, through the Fabric client entrypoint

Neither contains input logic. The core is loader-neutral:

java
public static KeyMapping[] createKeyMappings() { ... }
public static void bootstrap() { ... }
public static void initialize() { ... }
public static void onClientTick() { ... }
public static void shutdown() { ... }

The engine package

dev.inputbooster.engine is the input core:

ClassResponsibility
InputEngineThe state machine and the mode switch
KeyStateManagerThe authoritative held/released state per slot
KeyBindingProcessorMaps key codes to action slots
KeyboardProcessorTurns a key event into an engine state change
MouseProcessorTurns a button or scroll event into an engine state change
InputEventDispatcherThe single exit point that queues an action
CompatibilityManagerDetects input mods and resolves the engine mode
DiagnosticsManagerThe counters the overlay and settings screen read
ConfigurationManagerA thin façade over the config accessors

The input package

dev.inputbooster.input holds the three pieces that answer "who owns the keyboard right now":

ClassResponsibility
KeyboardRouterTracks whether a screen is open
KeyBindingSetThe twelve bound key codes, published per tick
RawKeyStateA handle to the window for raw platform key state

The feature package

dev.inputbooster.feature holds one class per feature. Every one of them is ticked from InputBoosterMod.onClientTick() and gated by a config flag and by the module manager. See feature managers.

The mixin package

Ten mixins, all client side. Two observe input, one drains the queue, the rest attach the UI. See the mixin inventory.

The version shim

dev.inputbooster.compat.McVersion exists once per Minecraft version, in src/compat/mc26_2 and src/compat/mc26_3. The build includes exactly one of them.

It hides the differences between 26.2 and 26.3 that the mod actually touches:

DifferenceShim method
The swing call changed shapeMcVersion.swingArm(player)
InputConstants.isKeyDown takes a window handle in 26.2 but not in 26.3McVersion.isKeyDown(key)
Sneak and jump state accessMcCompat.setSneaking, McCompat.isInWater, McCompat.isClimbing

Threading model

ThreadWhat it touches
Game threadEverything Minecraft, the drainer, the tick handlers
Polling threadRaw key state and the published binding set only

The polling thread never touches a Minecraft object. The window handle and the binding set are captured on the game thread and published as volatile fields.

The lifecycle

Construction

bootstrap() creates the key mappings. Nothing else happens yet.

First tick

onClientTick() calls initialize(), which verifies the mixin targets, loads the config, creates every manager, detects input mods, starts the poller and logs Ready!.

Running

Each tick: publish bindings, update the poll rate, run the combo keys, tick the feature managers, tick the drainer via the mixin.

Shutdown

The close mixin calls shutdown(), which stops the poller and waits for it, clears the queue, saves the config and releases the keyboard.