Minecraft Modding Skill
Overview
This skill guides Codex through developing open-source Minecraft mods. Target platforms:
Platform MC Version Java Build System
NeoForge 1.21.1 / 1.21.4 / 1.21.5 Java 21 Gradle + ModDevGradle
Fabric 1.21.1 / 1.21.4 Java 21 Gradle + Fabric Loom
Architectury (multiloader) 1.21.x Java 21 Gradle + Architectury Loom
Always confirm the platform and Minecraft version from gradle.properties or build.gradle
before writing any mod-specific code.
Routing Boundaries
-
Use when : the task is Java/Kotlin mod code, registry/event work, networking, datagen wiring, and loader APIs.
-
Do not use when : the task is command-only vanilla logic (minecraft-commands-scripting ) or pure datapacks (minecraft-datapack ).
-
Do not use when : the task targets Paper/Bukkit plugins (minecraft-plugin-dev ).
- Identifying the Platform
NeoForge project signature
grep -r "net.neoforged" gradle.properties build.gradle settings.gradle 2>/dev/null | head -5
Fabric project signature
grep -r "fabric" gradle.properties build.gradle settings.gradle 2>/dev/null | head -5
Read mod ID and version
cat gradle.properties
Key files per platform:
-
NeoForge: src/main/resources/META-INF/neoforge.mods.toml , annotated @Mod main class
-
Fabric: src/main/resources/fabric.mod.json , class implementing ModInitializer
-
Architectury: common/ , fabric/ , neoforge/ subprojects
- Build & Test Commands
Build the mod jar
./gradlew build
Run the Minecraft client to test
./gradlew runClient
Run a dedicated server to test
./gradlew runServer
Run game tests (NeoForge JUnit-style game tests)
./gradlew runGameTestServer
Run data generation (generates JSON assets automatically)
./gradlew runData
Clean build cache
./gradlew clean
Check for dependency updates (optional)
./gradlew dependencyUpdates
After ./gradlew build , the mod jar is at: build/libs/<mod_id>-<version>.jar
- Project Layout (NeoForge)
src/ main/ java/<groupId>/<modid>/ MyMod.java ← @Mod entry point block/ ModBlocks.java ← DeferredRegister<Block> MyCustomBlock.java item/ ModItems.java ← DeferredRegister<Item> entity/ ModEntities.java ← DeferredRegister<EntityType<?>> menu/ ← custom GUI containers recipe/ worldgen/ datagen/ ModDataGen.java ← GatherDataEvent handler providers/ resources/ META-INF/ neoforge.mods.toml ← mod metadata (renamed from mods.toml in NeoForge 1.20.5+) assets/<modid>/ blockstates/ ← JSON blockstate definitions models/ block/ ← block model JSON item/ ← item model JSON textures/ block/ ← 16×16 PNG textures item/ lang/ en_us.json ← translation strings data/<modid>/ recipes/ ← crafting recipe JSON loot_table/ blocks/ ← per-block loot table JSON tags/ blocks/ items/
- Project Layout (Fabric)
src/ main/ java/<groupId>/<modid>/ MyMod.java ← implements ModInitializer client/ MyModClient.java ← implements ClientModInitializer block/ item/ mixin/ ← Mixin classes resources/ fabric.mod.json assets/<modid>/ ← same as NeoForge data/<modid>/ ← same as NeoForge <modid>.mixins.json ← mixin configuration
- Core Concepts Cheatsheet
Sides
-
Physical client – the game client JAR (has rendering code)
-
Physical server – the dedicated server JAR (no rendering)
-
Logical client – the client thread (handles rendering, input)
-
Logical server – the server thread (handles world simulation)
-
Code decorated with @OnlyIn(Dist.CLIENT) (NeoForge) or @Environment(EnvType.CLIENT) (Fabric) must NEVER run on the server.
Registries
Everything in Minecraft lives in a registry. Always register objects; never construct them at field initializer time outside a registry call.
-
Blocks → Registry.BLOCK
-
Items → Registry.ITEM
-
Entity types → Registry.ENTITY_TYPE
-
Block entity types → Registry.BLOCK_ENTITY_TYPE
-
Menu types → Registry.MENU (NeoForge) / Registry.MENU_TYPE (Fabric)
-
Sound events → Registry.SOUND_EVENT
-
Biomes → Registry.BIOME
ResourceLocation / Identifier
Every registry entry needs a namespaced ID:
// NeoForge / vanilla Java ResourceLocation id = ResourceLocation.fromNamespaceAndPath("mymod", "my_block");
// Fabric (same class, same API in 1.21) Identifier id = Identifier.of("mymod", "my_block");
- NeoForge Quick Patterns
See full patterns in references/neoforge-api.md .
// Main mod class @Mod(MyMod.MOD_ID) public class MyMod { public static final String MOD_ID = "mymod";
public MyMod(IEventBus modEventBus) {
ModBlocks.BLOCKS.register(modEventBus);
ModItems.ITEMS.register(modEventBus);
modEventBus.addListener(this::commonSetup);
}
private void commonSetup(FMLCommonSetupEvent event) {
// runs after all mods are registered
}
}
// Block registration public class ModBlocks { public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(BuiltInRegistries.BLOCK, MyMod.MOD_ID);
public static final DeferredBlock<Block> MY_BLOCK =
BLOCKS.registerSimpleBlock("my_block",
BlockBehaviour.Properties.of()
.mapColor(MapColor.STONE)
.strength(1.5f, 6.0f)
.sound(SoundType.STONE)
.requiresCorrectToolForDrops());
}
- Fabric Quick Patterns
See full patterns in references/fabric-api.md .
// Main mod class public class MyMod implements ModInitializer { public static final String MOD_ID = "mymod"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override
public void onInitialize() {
ModBlocks.register();
ModItems.register();
}
}
// Block registration public class ModBlocks { public static final Block MY_BLOCK = new Block( AbstractBlock.Settings.create() .mapColor(MapColor.STONE) .strength(1.5f, 6.0f) .sounds(BlockSoundGroup.STONE) .requiresTool() );
public static void register() {
Registry.register(Registries.BLOCK,
Identifier.of(MyMod.MOD_ID, "my_block"), MY_BLOCK);
}
}
- JSON Asset Templates
Always provide matching JSON assets for every registered block/item. Codex should generate or update these files alongside Java code.
See references/common-patterns.md for full JSON templates for:
-
Blockstate JSON
-
Block model JSON (cube, slab, stairs, fence, door, trapdoor, etc.)
-
Item model JSON
-
Loot table JSON
-
Recipe JSON (crafting_shaped, crafting_shapeless, smelting, blasting, stonecutting)
-
Language file (en_us.json ) entries
-
Tag JSON
- Data Generation
Prefer data generation over hand-authored JSON for maintainability.
// NeoForge – register data gen providers in GatherDataEvent @SubscribeEvent public static void gatherData(GatherDataEvent event) { DataGenerator gen = event.getGenerator(); PackOutput output = gen.getPackOutput(); ExistingFileHelper helper = event.getExistingFileHelper(); CompletableFuture<HolderLookup.Provider> lookupProvider = event.getLookupProvider();
gen.addProvider(event.includeClient(), new ModBlockStateProvider(output, helper));
gen.addProvider(event.includeClient(), new ModItemModelProvider(output, helper));
gen.addProvider(event.includeServer(), new ModRecipeProvider(output, lookupProvider));
gen.addProvider(event.includeServer(), new ModLootTableProvider(output, lookupProvider));
gen.addProvider(event.includeServer(), new ModBlockTagsProvider(output, lookupProvider, helper));
}
Run data generation with ./gradlew runData , then commit the generated files.
- Common Tasks Checklist
When adding a new block:
-
Block subclass (or use vanilla Block with properties)
-
Register in ModBlocks.BLOCKS / Registries.BLOCK
-
Register BlockItem in ModItems.ITEMS / Registries.ITEM
-
Blockstate JSON → assets/<modid>/blockstates/<name>.json
-
Block model JSON → assets/<modid>/models/block/<name>.json
-
Item model JSON → assets/<modid>/models/item/<name>.json (or inherits from block)
-
Texture PNG → assets/<modid>/textures/block/<name>.png
-
Loot table JSON → data/<modid>/loot_table/blocks/<name>.json
-
Language entry in en_us.json
-
Mine-with-correct-tool tag if hardness > 0
When adding a new item:
-
Item subclass (or use new Item(properties) )
-
Register in ModItems / Registries.ITEM
-
Item model JSON
-
Texture PNG
-
Language entry
-
Creative tab registration (NeoForge: BuildCreativeModeTabContentsEvent ; Fabric: ItemGroupEvents )
-
Recipe JSON if craftable
When adding a new entity:
-
Entity class (extends appropriate base: Mob , Animal , TamableAnimal , etc.)
-
EntityType registration
-
Renderer class (@OnlyIn(Dist.CLIENT) )
-
Model class (@OnlyIn(Dist.CLIENT) )
-
Register renderer in EntityRenderersEvent.RegisterRenderers (NeoForge) or EntityModelLayerRegistry (Fabric)
-
Spawn egg item (optional)
-
Spawn rules / biome modifier
- Open-Source Conventions
-
License: MIT or LGPL-3.0 — include LICENSE file and SPDX-License-Identifier header
-
Versioning: {mod_version}+{mc_version} (e.g., 2.0.0+1.21.1 )
-
Changelog: Keep CHANGELOG.md up to date with semver notes
-
Publishing: Use gradle-modrinth or curseforgegradle plugins for CurseForge / Modrinth
-
CI: GitHub Actions with ./gradlew build and ./gradlew runGameTestServer
-
PR conventions: Keep PRs scoped to a single feature; include asset files with Java changes
- References
-
NeoForge API patterns and event system: .agents/skills/minecraft-modding/references/neoforge-api.md
-
Fabric API patterns and mixin guide: .agents/skills/minecraft-modding/references/fabric-api.md
-
Blocks, items, recipes, commands, GUIs, datagen: .agents/skills/minecraft-modding/references/common-patterns.md
-
NeoForge official docs: https://docs.neoforged.net/
-
Fabric developer docs: https://docs.fabricmc.net/develop/
-
Architectury (multiloader): https://docs.architectury.dev/
-
Minecraft Wiki (data formats): https://minecraft.wiki/w/Java_Edition_data_values