Cooking your own launcher like Orion - OrionMinecraft/Orion GitHub Wiki

Cooking your own launcher like Orion

Orion's idea is pretty much to load bytecode transformers (or mixins supported by Mixin library) from mod jars.

This article shows how you can create your own simple launcher utilizing Mixin library (without obfuscation support) and few mixins

Prerequisites

Step 1: Figure out what libraries you must include, and what is provided by target software

Mixin requires:

  • Google Guava (relocateable)
  • Google GSON (relocateable)
  • Apache Log4j2 (not sure if relocateable)

LegacyLauncher (Orion fork) requires:

  • Apache Log4j2 (not sure if relocateable)
  • OW2 ASM (relocateable)
  • jopt-simple (relocateable)

Step 2: Bootstrap class

package foo.bar.baz;

import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.launch.MixinBootstrap;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;

import java.nio.file.Paths;
import java.util.List;

public final class Bootstrap implements ITweaker {
    public static String LAUNCH_TARGET = "net.minecraft.server.MinecraftServer";

    public static void main(String... args) {
        // Store original arguments in blackboard
        Launch.blackboard.put("originalArgs", args);

        // Launch LegacyLauncher with bootstrap class as a tweaker
        Launch.main(new String[] { "--tweakClass", Bootstrap.class.getName() });
    }

    @Override
    public void injectIntoClassLoader(@NotNull LaunchClassLoader launchClassLoader) {
        // Load libraries (optional)
        try {
            launchClassLoader.addURL(Paths.get("./lib/Foo.jar").toUri().toURL());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // Initialize Mixin library and set side to server
        MixinBootstrap.init();
        MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.SERVER);

        // Load mixins
        Mixins.addConfiguration("mixins.foo.json");
        Mixins.addConfiguration("mixins.bar.json");
    }

    @NotNull
    @Override
    public String[] getLaunchArguments() {
        return (String[]) Launch.blackboard.get("originalArgs");
    }

    @NotNull
    @Override
    public String getLaunchTarget() {
        return LAUNCH_TARGET;
    }

    @Override
    public void acceptOptions(@NotNull List<String> args) {

    }
}

Step 3: defining mixins

See tutorial about Mixin library in its wiki: https://github.com/SpongePowered/Mixin/wiki

Mixin json

This json file assumes that mixin classes are in eu.mikroskeem.helios.mod.mixins.inventory package

{
  "required": true,
  "minVersion": "0.6.15",
  "package": "eu.mikroskeem.helios.mod.mixins.inventory",
  "target": "@env(DEFAULT)",
  "compatibilityLevel": "JAVA_8",
  "server": [
    "MixinCraftItemStack",
    "MixinItemStack",
    "items.MixinCraftSkullMeta"
  ]
}

Mixin json file goes to jar root (e.g put it into src/main/resources directory in your jar)

Step 4: configuring Gradle to set Main-Class attribute on your jar and create fat jar (without relocation)

val jar by tasks.getting(Jar::class) {
    from(configurations["compile"].map<File, Any> { if(it.isDirectory) it else zipTree(it) })
    manifest {
        attributes(mapOf(
            "Main-Class" to "foo.bar.baz.Bootstrap"
        ))
    }
}

If you require relocation, look at Gradle shadow plugin

⚠️ **GitHub.com Fallback** ⚠️