LunarCN mod development - earthsworth/LunarClient-CN GitHub Wiki
If something wrong, please create a issue to help us improve this page
The example mod -> LunarMod-Example
Notify to developers
This is not a Java tutorial or a Mixin tutorial, you need to understand basic knowledge about Java and Mixin
Features will deprecate
- Use LunarGradle to decompile Minecraft, not Weave-Gradle (LunarGradle is underDevelop)
- Use LunarLauncherLib to launch LunarClient, not LunarClient Launcher
Contents will add in this tutorial
- Access Writer (need finish LunarGradle develop)
About LunarGradle
I will publish LunarGradle to Gradle Plugin Portal
Source: here
Setup workspace
- Create a project using Gradle build tool (dsl: groovy)
- Download latest LunarCN Loader API jar into libs folder
- Add
implementation fileTree(dir: "libs", include: ["*.jar"])
in block dependencies - Add plugin repo in settings.gradle
- Add
id 'com.github.weave-mc.weave-gradle' version 'bcf6ab0279'
in block plugins - Add Minecraft block
- Sync project
Download LunarCN Loader online
Anytimes repo.lunarcn.top will down, if muskf forget renew it
Today is 2023/10/22, muskf ran away :(
Plugins repo
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
maven {
name = 'JitPack'
url = 'https://jitpack.io'
}
}
}
Minecraft Block
minecraft {
version "1.8.9"
}
Mod config file
src/main/resources/lunarcn.mod.json
{
"mixinConfigs": [
"example.mixins.json" // Mixin configs
],
"entrypoints": [
"com.example.ModEntry" // Entry points
],
"hookPackage": [
"com.example.hooks" // Hook Class
]
}
Add Entry point for your addon
ModEntry.java
This class may statement in lunarcn.mod.json
package org.example;
import org.cubewhy.lunarcn.loader.api.ModInitializer;
public class ModEntry implements ModInitializer {
@Override
public void onCrash(@NotNull CrashReport crashReport) {
System.out.println("OOPS, game crashed, LOG = " + crashReport.getFile().getPath());
}
@Override
public void onInit() {
System.out.println("Lunar init!");
}
@Override
public void onPreInit() {
System.out.println("Init mod!");
}
@Override
public void onStart() {
System.out.println("Game started!");
}
@Override
public void onStop() {
System.out.println("See you again");
}
}
Add Mixins for your addon
This is a example, here isn't a Mixin tutorial
If you want use Mixin in your addon, you need setup Mixin
Mixin config
You need add a mixin config in your project and statement it in Mod config file
src/main/resources/example.mixins.json
{
"required": true,
"minVersion": "0.8.5",
"package": "org.example.mixins", // Mixin package
"compatibilityLevel": "JAVA_8",
"mixins": [
"MixinMinecraft" // Mixins you have
]
}
Mixin classes
examples only
Make sure add className into mixins config
MixinMinecraft.java
package org.example.mixins;
import net.minecraft.client.Minecraft;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Inject(method = "startGame", at = @At("HEAD"))
public void startGameHead(CallbackInfo ci) {
System.out.println("Starting game!");
}
@Inject(method = "startGame", at = @At("RETURN"))
public void startGameReturn(CallbackInfo ci) {
System.out.println("Init finished!");
}
}
Setup Mixin
Add codes into build.gradle
repositories {
maven { url = "https://repo.spongepowered.org/repository/maven-public/" }
}
dependencies {
compileOnly 'org.spongepowered:mixin:0.8.5'
}
And rebuild your project
Add Hooks for your addon
Make sure add this className into Mod config
HookMinecraft.java
package org.example.hooks;
import org.cubewhy.lunarcn.loader.api.Hook;
import org.jetbrains.annotations.NotNull;
import org.cubewhy.lunarcn.loader.api.SubscribeHook;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
@SubscribeHook // 1.3+ uses subscribeHook to register a hook
public class HookMinecraft extends Hook {
public HookMinecraft() {
super("net/minecraft/client/Minecraft"); // The target class
}
@Override
public void transform(@NotNull ClassNode classNode, @NotNull AssemblerConfig assemblerConfig) {
classNode.methods.stream()
.filter(m -> m.name.equals("startGame")) // find target method
.findFirst().orElseThrow()
.instructions.insert(
new MethodInsnNode(
Opcodes.INVOKESTATIC,
Type.getInternalName(HookMinecraft.class), // where the method onStartGame is
"onStartGame", // invoke onStartGame
"()V"
)
);
}
public static void onStartGame() {
System.out.println("Minecraft Hook!");
}
}
Run your addon
- Launch LunarCN and close it
- Put your plugin into ~/.cubewhy/lunarcn/mods folder
- Run ~/.cubewhy/lunarcn/launch.bat
- Then you can see the log in the console