Manually writing JSON model, blockstate, and item definition files is tedious and error-prone. NeoForge's data generation system can produce these files automatically. In this tutorial we configure it to output directly into the common project so Fabric picks them up too, then replace our hand-authored files with a single generated provider.
NEW_DIRT block and IRON_STICK item from those tutorials.Configuring Common Output
By default NeoForge datagen writes into a generated folder inside the NeoForge subproject. We want the output in common instead, so both loaders can reference the same files.
Open the common subproject's build.gradle and make two changes. First, add the generated resources directory as a source set before the dependencies block:
Second, update the artifacts block so the common jar includes all resource directories, not just the first one:
Updating NeoForge Data Config
Open the neoforge subproject's build.gradle and update the data run configuration block so it outputs to common and uses your existing resources to resolve conflicts:
The --output flag routes generated files into common, and --existing tells the generator to resolve any file conflicts against your manually authored resources.
Hit the Gradle refresh button after saving both files.
Model Provider
In 26.1, the model system was reworked. Block models, blockstate files, and item definition files are all generated through a single ModelProvider class rather than separate BlockStateProvider and ItemModelProvider classes from older NeoForge versions.
In your NeoForge subproject, create a data package and add a class called ExampleModelProvider extending ModelProvider. Override registerModels, which receives a BlockModelGenerators for block resources and an ItemModelGenerators for standalone item models:
createTrivialCube generates a cube_all block model using the block's registry name as the texture path, plus the matching blockstate file. It does not automatically produce an item definition, so you follow it immediately with registerSimpleItemModel to write the items/ definition that points the inventory slot at the block model.
registerSimpleFlatItemModel handles standalone items in one call: it creates a minecraft:item/generated model JSON and then writes the matching items/ definition that references it.
BlockModelGenerators has helpers such as createAxisAlignedPillarBlock for logs and pillars, createDoor, createTrapdoor, and createSlab. Use them the same way in place of createTrivialCube.Registering the Provider
Model providers are client-side resources, so they are registered through GatherDataEvent.Client rather than the general GatherDataEvent. In your NeoForge mod class constructor, add a listener:
Then add the static handler method:
event.createProvider wires the provider into the generator automatically, handling pack output routing and file writing. Server-side providers (loot tables, recipes, tags) will be registered through a separate GatherDataEvent listener in later tutorials.
Running Datagen
Before running the generator, delete the existing hand-authored files from your common project's resources. Remove the blockstates/, models/block/, models/item/, and items/ directories, but keep your textures as these are not generated.
Open the Run Configurations dropdown and select NeoForge Data. After it completes successfully you will see a generated folder appear in your common project containing five files:
assets/examplemod/blockstates/new_dirt.jsonassets/examplemod/models/block/new_dirt.jsonassets/examplemod/items/new_dirt.jsonassets/examplemod/models/item/iron_stick.jsonassets/examplemod/items/iron_stick.json
registerModels and re-run NeoForge Data. The generator overwrites only the files it manages, leaving your textures and other hand-authored resources untouched.In the next tutorial we use datagen to generate block loot tables so your blocks actually drop items when broken.
You can find the source for this tutorial here:
View Source on GitHubData Generation: Block Loot Tables (MultiLoader 26.1+)
Write a BlockLootSubProvider that makes your custom blocks drop themselves, add it to a LootTableProvider, register everything through GatherDataEvent, and verify drops in-game.
Continue →