Build Your First Minecraft Block with Universal Modder
Use Universal Modder to plan and build Signal Block, one small Minecraft Java mod with a clear result: you can obtain it, place it, see its name and check its texture in a new practice world. The agent helps investigate the instance, edit a fixed Fabric project, inspect the build and keep a record of actual checks.
The external template does not already contain Signal Block. The exercise references the base game's gold-block texture by identifier, so it needs no generated artwork, copied game texture or fal connection. For other editions or loaders, begin with the Minecraft route guide.
Prerequisites
Use your own Minecraft Java Edition and a project you can modify. Prepare Git, a JDK 21 installation, network access for dependencies, and an isolated game instance. Exit the game and back up saves you want to keep. Start the exercise in a new practice world; keep important saves outside it.
Complete Universal Modder installation in the agent you intend to use. Keep MODDING_PLAN.md for the agreed work and MODLOG.md for commands, changed paths and results. The general tutorial explains that workflow. Keep optional asset services disabled for this exercise.
Ask Universal Modder to investigate
Run these in your agent's terminal:
um kb search "Minecraft"
um scan "Minecraft"You can select the code to copy it manually.
If the scan finds only the launcher or misses the installation, inspect the actual profile and pass the practice instance path to um scan. Confirm Java Edition, game version, loader, Game Directory and runtime in the launcher and logs. The scan can mistake the launcher's executable for the game; see the Minecraft investigation step.
Use this suggested agent prompt after the version table below is available:
Use game-recon and mod-any-game to plan the Signal Block exercise.
Compare the actual instance with the guide's exact Fabric 1.21.11 group.
Use official Mojang mappings and the pinned template commit.
Write MODDING_PLAN.md with the source files, backup and restore paths,
build commands and obtain/place/name/appearance checks.
Use a separate practice profile and a new world.
Record unknowns and do not modify my normal worlds.You can select the code to copy it manually.
Review that plan before implementation. For an existing instance, close the game and back up its actual save and configuration folders with the backup workflow. Record the snapshot location and restore procedure. The empty practice instance still needs a distinct directory; a new profile name alone does not isolate it.
Version conditions
| Component | Exact choice |
|---|---|
| Game | Minecraft Java Edition 1.21.11 |
| Fabric Loader | 0.18.6 |
| Fabric API | 0.141.3+1.21.11 |
| Source snapshot | FabricMC/fabric-example-mod, 1a7e9cdb0e65bb23890ebadfe029bca03bcd755c |
| Mappings | Official Mojang names, loom.officialMojangMappings() |
| Loom | 1.15.5; replace the template's 1.15-SNAPSHOT before any Gradle command |
| Plugin ID | net.fabricmc.fabric-loom-remap |
| Gradle wrapper | 9.3.0 |
| Java | JDK 21 for compilation and Gradle; check the game's actual Java separately |
The fixed Fabric source defines these values. Fabric's 1.21.11 development setup specifies JDK 21; Gradle 9.3.0's compatibility table includes Java 21. The published Loom 1.15.5 metadata fixes the template's moving snapshot dependency.
Keep this group together. A newer moving template branch can require different tools. Do not substitute Yarn class names or a global Gradle installation. Ignore the manifest's wider version ranges and build against this exact group.
Create project
In your ordinary terminal, from a safe parent folder where first-block does not already exist:
git clone --branch 1.21.11 https://github.com/FabricMC/fabric-example-mod.git first-block
cd first-block
git checkout --detach 1a7e9cdb0e65bb23890ebadfe029bca03bcd755cYou can select the code to copy it manually.
Keep the template's com.example package and modid namespace, main/client entrypoints, mixins and icon settings. Its root project name is modid and Mod version is 1.0.0. The folder name does not change the output JAR's name.
Open gradle.properties and change only the Loom version to:
loom_version=1.15.5You can select the code to copy it manually.
Confirm the other properties match the table. Then check java --version and javac --version in this environment; both should be 21. If needed, install Temurin 21 JDK, rather than a JRE. Set the IDE's Gradle JVM to the same JDK when using an IDE.
From the project root, use PowerShell on Windows:
java --version
javac --version
.\gradlew.bat --versionYou can select the code to copy it manually.
On macOS or Linux:
java --version
javac --version
./gradlew --versionYou can select the code to copy it manually.
If only this project's script lacks execute permission, use chmod +x gradlew. The wrapper check should show Gradle 9.3.0 and its actual JVM 21. WSL and host Java are separate checks. Stop on a mismatch and use version diagnosis. The first wrapper invocation may download dependencies; a network error is a different failure stage.
Review the agent's proposed changes
After the template and environment checks, give the agent a narrow implementation task:
Implement Signal Block using only the file steps in this guide.
Keep the template's modid namespace, entrypoints and official Mojang mappings.
Add the block and item registration, creative-tab entry and listed JSON files.
Reference minecraft:block/gold_block instead of copying a game texture.
Show the changed-file list and explain each edit before building.
Run only one Gradle task at a time and retain actual failures in MODLOG.md.
Do not report the game checks as passed until they are observed.You can select the code to copy it manually.
Review its changes against the code and paths below. The registration and resource layout follow Fabric's first-block documentation for 1.21.11. If the agent proposes identifiers from another version or mapping system, resolve that difference before proceeding.
Register block
Create src/main/java/com/example/SignalBlocks.java. The block and its inventory item use the same ID, modid:signal_block, with separate registry keys:
package com.example;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.Identifier;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
public final class SignalBlocks {
public static final Block SIGNAL_BLOCK = register();
private SignalBlocks() {}
private static Block register() {
Identifier id = Identifier.fromNamespaceAndPath(ExampleMod.MOD_ID, "signal_block");
ResourceKey<Block> blockKey = ResourceKey.create(Registries.BLOCK, id);
Block block = new Block(BlockBehaviour.Properties.of().setId(blockKey).strength(1.5F));
Registry.register(BuiltInRegistries.BLOCK, blockKey, block);
ResourceKey<Item> itemKey = ResourceKey.create(Registries.ITEM, id);
Item item = new BlockItem(block, new Item.Properties().setId(itemKey).useBlockDescriptionPrefix());
Registry.register(BuiltInRegistries.ITEM, itemKey, item);
return block;
}
public static void initialize() {
ItemGroupEvents.modifyEntriesEvent(CreativeModeTabs.BUILDING_BLOCKS)
.register(entries -> entries.accept(SIGNAL_BLOCK.asItem()));
}
}You can select the code to copy it manually.
In src/main/java/com/example/ExampleMod.java, keep MOD_ID as modid and add this line inside its existing onInitialize method:
SignalBlocks.initialize();You can select the code to copy it manually.
Calling initialize loads this class and registers its static block once. Do not call it from a second initializer or replace the template's entrypoint with an unrelated class.
Add resources
Create the parent folders as needed. All paths below are relative to the project root, and all IDs use modid consistently.
Block state
src/main/resources/assets/modid/blockstates/signal_block.json:
{
"variants": {
"": { "model": "modid:block/signal_block" }
}
}You can select the code to copy it manually.
Block model
src/main/resources/assets/modid/models/block/signal_block.json:
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "minecraft:block/gold_block" }
}You can select the code to copy it manually.
This references a built-in texture name; you do not need to copy a game PNG into the project.
Inventory item model
src/main/resources/assets/modid/items/signal_block.json:
{
"model": {
"type": "minecraft:model",
"model": "modid:block/signal_block"
}
}You can select the code to copy it manually.
Use this items path for the version in the table. An older models/item file alone does not supply the same item definition.
Display name
src/main/resources/assets/modid/lang/en_us.json:
{
"block.modid.signal_block": "Signal Block"
}You can select the code to copy it manually.
If you already have this language file, add the entry while preserving valid JSON and its other entries.
Survival drop
src/main/resources/data/modid/loot_table/blocks/signal_block.json:
{
"type": "minecraft:block",
"pools": [{
"rolls": 1,
"entries": [{ "type": "minecraft:item", "name": "modid:signal_block" }],
"conditions": [{ "condition": "minecraft:survives_explosion" }]
}]
}You can select the code to copy it manually.
The folder is singular loot_table. No recipe is included in this exercise: first obtain the block from Creative or the give command in your own cheats-enabled practice world.
Build
From the project root in Windows PowerShell:
.\gradlew.bat buildYou can select the code to copy it manually.
On macOS or Linux:
./gradlew buildYou can select the code to copy it manually.
The expected ordinary artifact is build/libs/modid-1.0.0.jar. Wait for your own build result; do not copy an old artifact after a failed build. A sources or development JAR is not the intended game package.
Inspect the JAR using the JDK tool:
jar tf build/libs/modid-1.0.0.jarYou can select the code to copy it manually.
Look for fabric.mod.json, com/example/SignalBlocks.class, the blockstates/models/items/lang files, and data/modid/loot_table/blocks/signal_block.json. If a file is missing, fix the project and rebuild before installation. Have the agent record the command, actual exit result, changed files and JAR inspection in MODLOG.md. If it cannot run a command, record that limitation.
Select instance
Use Fabric's installer to choose Minecraft 1.21.11 and Loader 0.18.6 for the official launcher. Create or edit its practice profile so Game Directory points to an isolated directory you chose. Confirm the profile's Java runtime matches the target; your terminal's java --version alone does not identify the launcher runtime.
Obtain Fabric API 0.141.3+1.21.11 and confirm the version on its download page. With the game closed, place that API JAR and your ordinary modid-1.0.0.jar in the practice directory's mods folder. Keep only one copy of this experiment. Do not place the source repository or unrelated archives there.
For a third-party launcher, identify its own Java/Fabric instance and directory using its instructions. If you cannot identify those conditions, stop and return to the Minecraft route.
Check loading
Choose the practice Fabric profile, start the game and create a new Creative practice world. Check that the selected profile and this instance's logs/latest.log correspond to Minecraft Java Edition 1.21.11 and the intended loader. A Mod menu is not required for this exercise.
Find Signal Block in the Building Blocks tab. In your own practice world with cheats enabled, you can instead use:
/give @s modid:signal_blockYou can select the code to copy it manually.
Obtain and place the block. Check the displayed name and gold-block appearance, and record the actual result. Have the agent compare the actual log and a screenshot you review with the plan's acceptance checks. If you operate the game yourself, report the observation accurately and keep a pending result where you have not checked it. Only the in-game check confirms the block works; a title screen, Mod listing or completed build covers earlier stages. This exercise adds no crafting recipe.
If you separately check drops in Survival, breaking this block should use the loot table you added. Breaking a block in Creative normally does not drop it; use the intended mode before diagnosing the loot file.
If a step fails
- Version, loader, Java or dependency error: stop before loading an important save. Use version diagnosis, then return to version conditions or build.
- Build failure: retain the failed task and first useful cause. Recheck the fixed snapshot, Loom edit, JDK, mapping names, initializer and resource paths. A dependency download failure needs a network check; do not install a stale JAR or disable system protection.
- Unknown block or missing experiment: use loading diagnosis to inspect the selected profile, actual directory, ordinary JAR and main initialization. The unedited external template has no Signal Block.
- Block exists but its appearance or name is wrong: inspect blockstates, models/block, items and lang inside the JAR. For Survival drops, inspect the singular loot_table directory and its ID. Reloading resources cannot register an uninitialized block.
- Crash: inspect the same instance's logs/latest.log and crash-reports. Record the time, versions and first useful cause. Close the game and move only this experiment's JAR out for a recovery check. Remove personal paths and credentials before sharing logs with a support channel you choose.
Uninstall
Exit the game and agent. Move only this experiment's modid-1.0.0.jar from the practice instance's mods folder to a backup folder outside mods. Keep Fabric API if other Mods need it, and preserve their files. Do not delete the entire instance or saves.
Start the same practice profile with a new world to check that it runs without this block. Keep the source, Mod plan, MODLOG and backups. A world containing custom blocks can lose data after their Mod is removed. For an important world, restore the backup taken before adding the Mod and use its original versions and environment. Do not open that save without the Mod to test removal.
Continue
Ask the agent to summarize the observed checks and remaining work in MODLOG.md, then preserve that source state before adding a feature. A crafting recipe is a smaller next step than a new entity or generated asset pipeline. Use the Minecraft prompts or prompt library to keep the next request bounded.
To apply the same one-feature learning process in another game, compare Terraria's first-item route, which uses C# and tModLoader rather than Java and Fabric. The game guide directory helps you choose that next project by its authoring tools; keep this working exercise intact while learning a new stack.
If you change Minecraft or its loader, investigate a new compatible group and recheck the code and resources. This fixed exercise is not an upgrade recipe. The Minecraft playbook on GitHub and broader case studies can help choose the next route.
Frequently asked questions
Can the agent do the whole first-block exercise?
It can investigate files, propose and apply source edits, run available build tools and inspect outputs. Actual game verification still needs an observable practice session. Record game checks as pending when neither the agent nor you has performed them.
Can I use a newer Minecraft or Fabric version?
This exercise fixes Minecraft 1.21.11, Loader 0.18.6, API 0.141.3+1.21.11 and the listed source and build tools. A different version needs its own API, mappings and resource checks; changing the version numbers alone does not port the mod.
Where can I download the finished Signal Block JAR?
There is no prebuilt download. Use the pinned source template, make the changes in this guide, build your own artifact and inspect it before installing it in the practice instance.