Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Scriptcraft | 1,473 | 3 years ago | 72 | mit | JavaScript | |||||
Write Minecraft Plugins in JavaScript. | ||||||||||
Minecraftdev | 1,152 | a day ago | 199 | mit | Kotlin | |||||
Plugin for IntelliJ IDEA that gives special support for Minecraft modding projects. | ||||||||||
Yarn | 740 | 7 hours ago | 126 | cc0-1.0 | Java | |||||
Libre Minecraft mappings, free to use for everyone. No exceptions. | ||||||||||
Figura | 218 | 10 months ago | 40 | lgpl-2.1 | Java | |||||
Primary repo for the Figura Project | ||||||||||
Openminer | 215 | a month ago | 53 | lgpl-2.1 | C++ | |||||
Minecraft-like game engine written in C++17 with a client/server architecture and support for Lua modding | ||||||||||
Chunkstories | 204 | a year ago | 2 | lgpl-3.0 | Kotlin | |||||
Somewhat fancy blocky game engine written in Kotlin | ||||||||||
Illegal Mod Sites | 177 | a day ago | 17 | other | Python | |||||
📜 A list of websites that are illegally redistributing game mods | ||||||||||
Pax | 132 | 4 months ago | 16 | mit | Nim | |||||
📦 The MC modpack manager for professionals. | ||||||||||
Coffee | 100 | 2 months ago | 8 | gpl-2.0 | Java | |||||
The main client | ||||||||||
Minecraft Deobfuscator3000 | 91 | a year ago | 5 | mit | ||||||
Powerful and universal deobfuscator for Minecraft mods and java decompiler! |
Flint is a Minecraft modding framework created by LabyMedia GmbH. It is developed with a focus on responsibility-driven design, interface segregation and dependency injection. This allows for easy encapsulation of version-specific code. Flint makes heavy use of bytecode manipulation - Minecraft isn't patched directly - resulting in better compatibility between Mods and a simpler update process.
Warning: Flint is still in development and not stable yet. We are currently working with Minecraft 1.15.2 and 1.16.5, but will soon start to implement other versions (including 1.8.9).
Contributions are welcome, just make sure to take a look at our contribution guidelines first. We would also love to chat with you about Flint on our Discord Server. We always appreciate feedback.
Creating Minecraft modifications is often not as easy as it could be due to several challenges.
We learned from older projects and tried to approach these issues to make your life as a mod creator as easy as possible.
Many things can already be accomplished using Flint's version independent Minecraft API. There are however many tools provided to modify Minecraft even further. A few examples are listed below.
For event listener, Flint uses the @Subscribe
annotation. The event type will
be inferred from the method's parameter type.
@Subscribe
public void onTick(TickEvent tickEvent) {
if (tickEvent.getType() == TickEvent.Type.GENERAL)
System.out.println("Tick!");
}
Flint provides several ways for bytecode manipulation, including the popular
Javassist library as well as
objectweb ASM. Class transformations can easily be
performed by annotating an appropriate Method with @ClassTransform
.
@ClassTransform("net.minecraft.client.Minecraft")
public void transformMinecraft(ClassTransformContext ctx) throws CannotCompileException {
CtClass mcClass = ctx.getCtClass();
mcClass.addMethod(CtMethod.make(
"public void helloWorld() { System.out.println(\"Hello World!\"); }", mcClass));
}
With the help of the @Shadow
annotation, interfaces can be used to easily
access private fields or methods in Minecraft's classes.
@Shadow("net.minecraft.client.Minecraft")
public interface MinecraftAccessor {
@FieldGetter("gameDir")
File getGameDir();
}
Instances of that class can then be casted to the interface type to access fields and methods:
File gameDir = ((MinecraftAccessor) Minecraft.getInstance()).getGameDir();
Should the included events not suffice, a Mod can hook into arbitrary Minecraft
methods using the @Hook
annotation.
@Hook(
className = "net.minecraft.client.Minecraft",
methodName = "displayInGameMenu",
parameters = {@Type(reference = boolean.class)},
executionTime = Hook.ExecutionTime.BEFORE)
public void beforeInGameMenu(@Named("args") Object[] args) {
System.out.println("Opening the in-game Menu...");
}
Flint is build using a responsibility driven approach and dependency injection. For the latter, we currently use Google's Guice (the assisted factory extensions is not compatible though, however, a custom alternative is available).
To access the tools of the framework you won't call static getter methods but instead use constructor injection to retrieve the instance you need.
@Singleton
public class ChatHandler {
private final TaskExecutor executor;
@Inject
private ChatHandler(TaskExecutor executor) {
this.executor = executor;
}
@Subscribe
public void onChat(ChatSendEvent event) {
if (event.getMessage().equals("Remind me!")) {
this.executor.scheduleSync(60 * 20, () -> {
System.out.println("Reminder!");
});
}
}
}
There is no need to manually register the event listener. An instance of the
class will be constructed automatically using Guice, an appropriate instance of
the TaskExecutor
interface will be injected. For further explanations, see
the very comprehensive
Guice documentation.
When creating own interfaces and implementations, there is no need to manually
bind them together using a Guice module. Instead, the implementation should be
marked with the @Implement
annotation, which also allows for version-specific
implementations.
Assume a simple interface whose implementation performs an action that requires different implementations for different Minecraft versions.
public interface StuffDoer {
void doStuff();
}
Flint will then automatically bind the correct implementation for the running version.
// Class in 1.15.2 source set
@Implement(StuffDoer.class)
public class VersionedStuffDoer implements StuffDoer {
@Override
public void doStuff() {
// Since the class is in the 1.15.2 source set, this
// implementation will only be used for 1.15.2
}
}
Abstracting your version-specific code like this results in a strong encapsulation and helps you to write big parts of your Mod version independently.
Each Flint module (as well as Mods build using our Gradle plugin) is split up into multiple source sets.
The main
source set should contain interfaces and classes that make up the
public API of the module. This API must always be completely version
independent. Minecraft classes can't be accessed directly.
The internal
source set should contain version-independent implementations of
interfaces located in the main
source set.
you can add a source set for every supported Minecraft version. These source sets should contain version-specific implementations. Minecraft classes can be accessed directly. The resulting symbolic references will be remapped automatically at runtime to assure compatibility with both obfuscated and de-obfuscated Minecraft installations. Class transformations and alike should also go into these source sets.
Building Flint is fairly easy. The project is set up using Gradle and a custom Gradle plugin that manages source sets and dependencies. The Gradle plugin also downloads, decompiles and de-obfuscates Minecraft when building for the first time.
After cloning the repository, just run the build
task:
# Linux
$ ./gradlew build
# Windows
C:\...\FlintMC> gradlew.bat :build
There is also a task to start a de-obfuscated Minecraft directly out of your development environment.
# Linux
$ ./gradlew runClient1.16.5
# Windows
C:\...\FlintMC> gradlew.bat :runClient1.16.5
If you want to login into your Minecraft account, just set the following
property in your global Gradle property file (~/.gradle/gradle.properties
):
net.flintmc.enable-minecraft-login=true
When running the client, a login prompt will appear.
Getting started with Flint is not difficult. The project setup doesn't require deep Gradle knowledge and IDE support should be available without any extra steps.
To create a simple Mod, the first step is to set up a new Gradle project. We
will use the following build.gradle.kts
:
plugins {
id("java-library")
id("net.flintmc.flint-gradle")
}
repositories {
mavenCentral()
}
group = "your.group"
version = "1.0.0"
flint {
// Enter the newest Flint version here
flintVersion = "2.0.23"
minecraftVersions("1.15.2", "1.16.5")
authors = arrayOf("Your Name")
runs {
overrideMainClass("net.flintmc.launcher.FlintLauncher")
}
}
dependencies {
annotationProcessor(flintApi("annotation-processing-autoload"))
internalAnnotationProcessor(flintApi("annotation-processing-autoload"))
api(flintApi("framework-eventbus"))
api(flintApi("framework-inject"))
api(flintApi("mcapi"))
api(flintApi("util-task-executor"))
minecraft("1.15.2", "1.16.5") {
annotationProcessor(flintApi("annotation-processing-autoload"))
}
}
You will also need the following in your settings.gradle.kts
, otherwise
Gradle won't find our custom Gradle plugin.
pluginManagement {
plugins {
// make sure to use the newest version
id("net.flintmc.flint-gradle") version "2.8.1"
}
buildscript {
dependencies {
classpath("net.flintmc", "flint-gradle", "2.8.1")
}
repositories {
maven {
setUrl("https://dist.labymod.net/api/v1/maven/release")
name = "Flint"
}
mavenCentral()
}
}
}
You can then set up the source sets. The Gradle plugin expects the following structure:
.
src
internal/java/your/group/internal
main/java/your/group
v1_16_5/java/your/group/v1_16_5
If you now add the ChatHandler
class from the
Dependency Injection section, you will see that
Reminder!
is printed to the log output one minute after you wrote
Remind me!
into the chat.
The Flint gradle plugin can automatically generate a simple JAR installer. It will contain all the files needed by your mod and will also download and install dependencies (including Flint itself) if not already installed.
To generate the installer, just run following task:
$ ./gradlew bundledInstallerJar
For more comprehensive examples and tutorials, go to our developer documentation. There you will also find tutorials on how to publish your Mod to our distribution service.
This project is not yet finished, there are many things we still want to do.
NOT OFFICIAL MINECRAFT PRODUCT. NOT APPROVED BY OR ASSOCIATED WITH MOJANG.