> For the complete documentation index, see [llms.txt](https://ddozzi.gitbook.io/mixin-tutorial/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ddozzi.gitbook.io/mixin-tutorial/how-to-make-a-mixin-client/3-or-creating-a-tweaker.md).

# 3 | Creating a tweaker

### What is a tweaker?

A tweaker allows arguments to be passed into it, and then allow you to inject your mixins into the Minecraft class loader

### Making the class <a href="#making-the-class" id="making-the-class"></a>

So first, go to the mixins folder in your project heirachy

```
project
    -> src
        -> java
            -> group_name
                -> project_name
                    -> mixins <-- Go here
```

In the previous tutorial, in the `build.gradle` file, we set the tweakclass variable to something like so

```java
tweakClass = "me.ddozzi.exampleclient.mixins.ExampleClientTweaker"
```

Take the last part of that (the tweaker class name), and in the mixins folder create a class by that name. An image is shown below.

![A tweaker class inside the path specified in the build.gradle](/files/-MiIYHjJvdiboXu_4iFZ)

### Writing the tweaker

First, you need to implement the `ITweaker` interface, just add `implements ITweaker` to your class definition

```java
public class ExampleClientTweaker implements ITweaker {
}
```

Next, you should add the launch arguments array, this will store any launch arguments needed for later

```java
/**
    * This stores the Minecraft launch arguments  
    */
private List<String> launchArgs = new ArrayList<>();
```

Now we need to handle the launch arguments, or options, so you can simply just override `acceptOptions`

```java
/**
/**
    * This handles the launch arguments passed towards minecraft
    * @param args The launch arguments
    * @param gameDir The game directory (ie: .minecraft)
    * @param assetsDir The assets directory
    * @param profile The game profile
    */
@Override
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
    ...
}
```

Add the args to our `launchArgs` array, so we can use them later

```java
// Add the launch arguments to our launchArgs array
this.launchArgs.addAll(args);
```

We're going to only deal with 3 options, so we can easily define them as a set of constants

```java
// Constants
final String VERSION = "--version";
final String ASSET_DIR = "--assetDir";
final String GAME_DIR = "--gameDir";
```

Now we need to

1. Check if the launch args contains each constant, if not add it
2. Check if the profile isn't `null` (profile contains metadata about the game, for example, the version)

We can do this by checking with a few `if` statements like so

```java
// Check if version is passed as a launch argument, if not add it
if (!args.contains(VERSION) && profile != null) {
    launchArgs.add(VERSION);
    launchArgs.add(profile);
}

// Check if assetDir is passed as a launch argument, if not add it
if (!args.contains(ASSET_DIR) && profile != null) {
    launchArgs.add(ASSET_DIR);
    launchArgs.add(profile);
}

// Check if gameDir is passed as a launch argument, if not add it
if (!args.contains(GAME_DIR) && profile != null) {
    launchArgs.add(GAME_DIR);
    launchArgs.add(profile);
}
```

You also need to define a function for injection into the class loader

```java
/**
    * Inject into the MC class loader
    * @param classLoader The class loader
    */
@Override
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
    ...
}
```

For the injection function, you must first initialize `MixinBootsrap`, which is trivially done

```java
MixinBootstrap.init();
```

Next, we need to register out mixin configuration file and retrieve the default mixin environment

Just like in the `build.gradle` file, substitute `PROJECT_NAME` with your project's name

```java
// Retrieve the default mixin environment and register the config file
MixinEnvironment environment = MixinEnvironment.getDefaultEnvironment();

environment.addConfiguration("mixins.PROJECT_NAME.json");
```

Now we just need to check if there is no current obfuscation set, then set the obfuscation context to the `notch` obfuscation

```java
// Check if the obfuscation context is null
if (environment.getObfuscationContext() == null) {
    environment.setObfuscationContext("notch");
}
```

Now we need to inform Minecraft that this modification is running on the client side

```java
// This is a client side, client :)
environment.setSide(MixinEnvironment.Side.CLIENT);
```

Lastly, we just add the boiler plate which allows Minecraft to retrieve the launch arguments and the launch target

```java
@Override
public String getLaunchTarget() {
    return MixinBootstrap.getPlatform().getLaunchTarget();
}

@Override
public String[] getLaunchArguments() {
    return launchArgs.toArray(new String[0]);
}
```

{% hint style="info" %}
Having trouble? Check out the full [tweaker souce code here](https://gist.github.com/ddozzi/2292f9c25349e6b1f30b9808dd54193e).
{% endhint %}

{% hint style="success" %}
You should now be able to run the client!&#x20;
{% endhint %}

![Nice! We've launched Mixin Minecraft!](/files/-MiIvJzXe6XPla4wC1E6)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ddozzi.gitbook.io/mixin-tutorial/how-to-make-a-mixin-client/3-or-creating-a-tweaker.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
