Skip to content

Repository files navigation

Utils — Minecraft Client Mod

A client-side utility mod for Minecraft 1.20.1, built with Kotlin and Java on the Fabric modding framework. This project demonstrates bytecode manipulation, event-driven architecture, real-time UI overlays, and modular software design.

Quick Context: What is Minecraft Modding?

Minecraft is a Java application, but its source code is obfuscated and not designed for extension. Modding requires:

  1. Deobfuscation mappings — Translating obfuscated names (a, b, c) back to meaningful identifiers (PlayerEntity, render, health)
  2. Bytecode manipulation — Injecting custom code into compiled .class files at runtime using the SpongePowered Mixin framework
  3. A mod loaderFabric provides the toolchain for building, loading, and running mods

This is analogous to writing plugins for a closed-source application by patching its bytecode at load time.

Architecture

flowchart TB
subgraph runtime [Minecraft Runtime]
direction TB
subgraph injection [Bytecode Injection Layer]
Mixins[Java Mixins]
MC[Minecraft Internals]
Mixins -->|"@Inject, @Redirect"| MC
end
Mixins -->|fires| Events
Events[Event System]
Events -->|notifies| Modules
subgraph Modules [Kotlin Modules]
KeyHud[KeyHudModule]
Balance[BalanceTracker]
AutoClick[AutoClicker]
More[...]
end
Modules -->|renders| UI[OWO Lib UI]
end
Loading

Source Structure

src/
├── client/
│ ├── kotlin/ # Business logic, UI, feature modules
│ │ └── dev/u9g/utils/client/
│ │ ├── modules/ # Feature modules (AutoClicker, KeyHud, etc.)
│ │ ├── events/ # Custom event definitions
│ │ ├── component/ # Reusable UI components
│ │ └── config/ # JSON-based configuration
│ ├── java/ # Mixins (must be Java for bytecode manipulation)
│ │ └── dev/u9g/utils/mixin/client/
│ └── resources/ # Assets, mixin config JSONs
└── main/
└── kotlin/ # Server-side code (minimal)

Technical Skills Demonstrated

1. Bytecode Manipulation (Mixins)

Mixins inject code into Minecraft's compiled classes at runtime. Example from ChatScreenMixin.java:

@Mixin(ChatScreen.class)
publicabstractclassChatScreenMixinextendsScreen {
@ShadowprotectedEditBoxinput;
@Inject(method = "init", at = @At("TAIL"))
privatevoidmoveInputBoxUp(CallbackInfoci) {
this.input.setY(this.height - 12 - CHAT_Y_OFFSET);
}
@Inject(method = "render", at = @At("HEAD"), cancellable = true)
privatevoidrenderMoved(GuiGraphicsgraphics, intmouseX, intmouseY,
floatpartialTick, CallbackInfoci) {
// Custom rendering logic...ci.cancel(); // Prevent original method execution
}
}

Key concepts:

  • @Mixin — Target class to modify
  • @Shadow — Access private fields from the target
  • @Inject — Insert code at specific points (HEAD, TAIL, RETURN)
  • @Accessor — Generate getters/setters for private fields

2. Event-Driven Architecture

Custom events follow the Fabric EventFactory pattern:

// Event definitionobject GuiKeyPressedCallback {
valEVENT:Event<GuiKeyPressedCallback> =EventFactory.createArrayBacked(...)
}
// Registration (in a module)GuiKeyPressedCallback.EVENT.register { screen, keyCode, scanCode, modifiers ->// Handle key press
}

Modules are initialized in shuffled order to prevent implicit cyclic dependencies:

listOf(
BalanceTrackerModule::init,
ChatScreenOverlayModule::init,
AutoclickerModule::init,
// ...
).shuffled().forEach { it() }

3. Declarative UI Components

Using OWO Lib's fluent builder API:

Containers.grid(Sizing.content(), Sizing.content(), 3, 3)
.child(createButton("Up"), row =0, col =1)
.child(createButton("Left"), row =1, col =0)
.child(createButton("Down"), row =1, col =1)
.child(createButton("Right"), row =1, col =2)
.positioning(Positioning.relative(75, 25))
.surface(Surface.VANILLA_TRANSLUCENT)

4. Real-Time Data Parsing

The mod parses game state from multiple sources:

  • Scoreboard sidebar — Currency balances, game mode detection
  • Chat messages — Progress tracking via regex pattern matching
  • Entity data — Health values, names for targeting logic
valBALANCE_REGEX="\\| ((?:[\\d.]+)(?:E\\d+)|(?:[a-zA-Z]*)) (.+)".toRegex()
funparseBalances(lines:List<Component>): Map<String, String> {
return lines.mapNotNull { line ->BALANCE_REGEX.matchEntire(normalizeText(line.string))?.let { match ->val (amount, currency) = match.destructured
currency to amount
}
}.toMap()
}

5. Hot-Reloadable Module System

"Gen 2" modules implement the Reloadable interface for runtime reinitialization:

interfaceReloadable {
funinit(): () ->Unit // Returns cleanup function
}
// Usageval gen2Modules =listOf(KeyHudModule, AutoMoveModule)
gen2Modules.forEach { cleanup.add(it.init()) }
// On screen change, reinitializeOpenScreen.EVENT.register { _, _ ->
cleanup.forEach { it() }
cleanup.clear()
gen2Modules.forEach { cleanup.add(it.init()) }
}

Feature Summary

ModuleDescription
KeyHudModuleOn-screen HUD showing pressed keys (WASD, mouse, sprint)
AutoclickerModuleAutomated input with configurable CPS and target filtering
BalanceTrackerModuleParses scoreboard for currency tracking, detects game mode
ChatScreenOverlayModuleCommand button grid + progress sidebar overlay
HighlightItemsInGuiModuleVisual item replacement in inventory UIs
KillHistoryModuleTracks combat statistics

Tech Stack

TechnologyPurpose
Kotlin 2.3Primary language for business logic
Java 21Required for Mixin classes
Fabric LoaderMod loading framework
Fabric APIStandard hooks and events
SpongePowered MixinBytecode transformation
OWO LibDeclarative UI components
BaritonePathfinding integration
Gradle + Fabric LoomBuild toolchain with remapping
GSONJSON configuration persistence

Build & Run

# Build the mod JAR
./gradlew build
# Output: build/libs/Utils-1.0-SNAPSHOT.jar# Run Minecraft with the mod (development)
./gradlew runClient

Requires Java 21. The build uses Fabric Loom, which handles deobfuscation mappings and JAR remapping automatically.

License

All Rights Reserved

About

A Minecraft 1.20.1 client-side utility mod built with Kotlin and Java, featuring a modular architecture, custom event systems, bytecode injection via Mixins, and UI components.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages