Getting Started with Fabric

Why Choose Fabric?

Fabric offers several advantages for Minecraft modding:

  • Lightweight - Fabric has a minimal core that loads quickly and efficiently
  • Modular - The API is split into modules that can be used independently
  • Fast updates - Fabric typically updates to new Minecraft versions very quickly
  • Modern codebase - Built with modern Java features and practices
  • Growing ecosystem - A vibrant community creating libraries and mods

Setting Up Your Development Environment

Setting up for Fabric development is straightforward:

  1. Install Java Development Kit (JDK) 17 or higher

    Fabric requires JDK 17 or higher for the latest versions. Download it from Adoptium or Oracle.

  2. Choose an IDE

    We recommend IntelliJ IDEA or Eclipse for Java development.

  3. Use the Fabric Template Mod

    The easiest way to get started is to use the Fabric Example Mod as a template.

  4. Set up Gradle

    Fabric uses Gradle for building mods. The template mod already includes the necessary Gradle configuration.

    build.gradle (Fabric Mod)
    1234567891011121314151617181920
    // build.gradle
    plugins {
        id 'fabric-loom' version '1.3-SNAPSHOT'
        id 'maven-publish'
    }
    
    version = project.mod_version
    group = project.maven_group
    
    repositories {
        // Add repositories for dependencies here
    }
    
    dependencies {
        // Minecraft and Fabric API
        minecraft "com.mojang:minecraft:${project.minecraft_version}"
        mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
        modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
        modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
    }

Fabric Mod Basics

Mod Structure

A basic Fabric mod consists of the following components:

  • fabric.mod.json - The mod metadata file
  • Main mod class - The entry point for your mod
  • Mixin classes - For modifying Minecraft's code
  • Resources - Textures, models, and other assets

Here's an example of a fabric.mod.json file:

fabric.mod.json
12345678910111213141516171819202122232425262728293031323334
{
  "schemaVersion": 1,
  "id": "example-mod",
  "version": "${version}",
  "name": "Example Mod",
  "description": "This is an example mod for Fabric!",
  "authors": [
    "Your Name"
  ],
  "contact": {
    "homepage": "https://example.com/",
    "sources": "https://github.com/yourusername/example-mod"
  },
  "license": "MIT",
  "icon": "assets/example-mod/icon.png",
  "environment": "*",
  "entrypoints": {
    "main": [
      "com.example.examplemod.ExampleMod"
    ],
    "client": [
      "com.example.examplemod.ExampleModClient"
    ]
  },
  "mixins": [
    "example-mod.mixins.json"
  ],
  "depends": {
    "fabricloader": ">=0.14.21",
    "minecraft": "~1.20.1",
    "java": ">=17",
    "fabric-api": "*"
  }
}

Main Mod Class

The main class is the entry point for your mod. Here's a simple example:

ExampleMod.java
123456789101112131415161718
package com.example.examplemod;

import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExampleMod implements ModInitializer {
    // Create a logger
    public static final Logger LOGGER = LoggerFactory.getLogger("example-mod");

    @Override
    public void onInitialize() {
        // This code runs when your mod is initialized
        LOGGER.info("Example mod initialized!");
        
        // Register items, blocks, etc. here
    }
}

Registering Items and Blocks

Here's how to register a custom item in Fabric:

ItemRegistration.java
1234567891011121314151617181920212223242526272829
package com.example.examplemod;

import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.minecraft.item.Item;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.util.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExampleMod implements ModInitializer {
    public static final Logger LOGGER = LoggerFactory.getLogger("example-mod");
    
    // Define your custom item
    public static final Item CUSTOM_ITEM = new Item(new FabricItemSettings());

    @Override
    public void onInitialize() {
        LOGGER.info("Example mod initialized!");
        
        // Register the custom item
        Registry.register(
            Registries.ITEM,
            new Identifier("example-mod", "custom_item"),
            CUSTOM_ITEM
        );
    }
}

Advanced Fabric Concepts

Using Mixins

Mixins are a powerful way to modify Minecraft's code without directly editing it. Here's a simple example:

TitleScreenMixin.java
123456789101112131415
package com.example.examplemod.mixin;

import net.minecraft.client.gui.screen.TitleScreen;
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(TitleScreen.class)
public class TitleScreenMixin {
    @Inject(at = @At("HEAD"), method = "init()V")
    private void init(CallbackInfo info) {
        System.out.println("This line is printed by an example mod mixin!");
    }
}

You also need to configure your mixins in a JSON file:

example-mod.mixins.json
1234567891011121314
{
  "required": true,
  "minVersion": "0.8",
  "package": "com.example.examplemod.mixin",
  "compatibilityLevel": "JAVA_17",
  "mixins": [
  ],
  "client": [
    "TitleScreenMixin"
  ],
  "injectors": {
    "defaultRequire": 1
  }
}

Networking in Fabric

Fabric provides a simple API for networking between client and server:

NetworkingExample.java
1234567891011121314151617181920
// Server-side registration
public static final Identifier EXAMPLE_PACKET_ID = new Identifier("example-mod", "example_packet");

// Register the packet in your mod initializer
ServerPlayNetworking.registerGlobalReceiver(EXAMPLE_PACKET_ID, (server, player, handler, buf, responseSender) -> {
    // Read data from the packet
    String message = buf.readString(32767);
    
    // Execute on the server thread
    server.execute(() -> {
        System.out.println("Received message from client: " + message);
    });
});

// Client-side sending
public void sendExamplePacket() {
    PacketByteBuf buf = PacketByteBufs.create();
    buf.writeString("Hello from the client!");
    ClientPlayNetworking.send(EXAMPLE_PACKET_ID, buf);
}

Config Files

Fabric doesn't have a built-in config system, but you can use libraries like Cloth Config or create your own:

ConfigExample.java
12345678910111213141516171819202122232425262728293031323334353637383940
// Using Cloth Config with TOML
public class ModConfig {
    private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
    private static final File CONFIG_FILE = new File("config/example-mod.json");
    
    public static ModConfigData CONFIG = new ModConfigData();
    
    public static class ModConfigData {
        public boolean enableFeature = true;
        public int cooldownTicks = 20;
        public String welcomeMessage = "Hello, world!";
    }
    
    public static void load() {
        try {
            if (CONFIG_FILE.exists()) {
                BufferedReader reader = new BufferedReader(new FileReader(CONFIG_FILE));
                CONFIG = GSON.fromJson(reader, ModConfigData.class);
            } else {
                save(); // Create default config
            }
        } catch (Exception e) {
            System.err.println("Error loading config: " + e.getMessage());
        }
    }
    
    public static void save() {
        try {
            if (!CONFIG_FILE.getParentFile().exists()) {
                CONFIG_FILE.getParentFile().mkdirs();
            }
            
            FileWriter writer = new FileWriter(CONFIG_FILE);
            GSON.toJson(CONFIG, writer);
            writer.close();
        } catch (Exception e) {
            System.err.println("Error saving config: " + e.getMessage());
        }
    }
}