Skip to content
/ Utils Public

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.

License

Notifications You must be signed in to change notification settings

u9g/Utils

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)
public abstract class ChatScreenMixin extends Screen {
    @Shadow protected EditBox input;

    @Inject(method = "init", at = @At("TAIL"))
    private void moveInputBoxUp(CallbackInfo ci) {
        this.input.setY(this.height - 12 - CHAT_Y_OFFSET);
    }

    @Inject(method = "render", at = @At("HEAD"), cancellable = true)
    private void renderMoved(GuiGraphics graphics, int mouseX, int mouseY,
                             float partialTick, CallbackInfo ci) {
        // 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 definition
object GuiKeyPressedCallback {
    val EVENT: 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
val BALANCE_REGEX = "\\| ((?:[\\d.]+)(?:E\\d+)|(?:[a-zA-Z]*)) (.+)".toRegex()

fun parseBalances(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:

interface Reloadable {
    fun init(): () -> Unit  // Returns cleanup function
}

// Usage
val gen2Modules = listOf(KeyHudModule, AutoMoveModule)
gen2Modules.forEach { cleanup.add(it.init()) }

// On screen change, reinitialize
OpenScreen.EVENT.register { _, _ ->
    cleanup.forEach { it() }
    cleanup.clear()
    gen2Modules.forEach { cleanup.add(it.init()) }
}

Feature Summary

Module Description
KeyHudModule On-screen HUD showing pressed keys (WASD, mouse, sprint)
AutoclickerModule Automated input with configurable CPS and target filtering
BalanceTrackerModule Parses scoreboard for currency tracking, detects game mode
ChatScreenOverlayModule Command button grid + progress sidebar overlay
HighlightItemsInGuiModule Visual item replacement in inventory UIs
KillHistoryModule Tracks combat statistics

Tech Stack

Technology Purpose
Kotlin 2.3 Primary language for business logic
Java 21 Required for Mixin classes
Fabric Loader Mod loading framework
Fabric API Standard hooks and events
SpongePowered Mixin Bytecode transformation
OWO Lib Declarative UI components
Baritone Pathfinding integration
Gradle + Fabric Loom Build toolchain with remapping
GSON JSON 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

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published