Mod Development Tools
Gradle handles three tasks that you would otherwise repeat every time you make a mod.
| Tool | What it does | Command |
|---|---|---|
initPolyMod | Turns an unzipped copy of the mod template into a new mod: replaces the mod ID, package, and class names everywhere | initPolyMod -PmodId=… in the unzipped template |
polyResources | At build time, generates the JSON you used to write by hand for each block and item (model, block state, item definition, loot, name, tool tag) | One line in build.gradle.kts |
checkPolyResources | Finds uppercase file names, broken JSON, missing models and textures, and missing namespaces before you start the game | Included in build and check |
Create a new mod: initPolyMod
Run it in the folder of an unzipped mod template (Get the mod template). Only the mod ID is required.
- Windows (PowerShell)
- macOS · Linux (bash)
.\gradlew.bat initPolyMod -PmodId=ruby_mod "-PmodName=Ruby Mod" "-PmodPackage=io.github.you.ruby"
.\gradlew.bat build
./gradlew initPolyMod -PmodId=ruby_mod "-PmodName=Ruby Mod" "-PmodPackage=io.github.you.ruby"
./gradlew build
| Property | Default | Example |
|---|---|---|
modId (required) | — | ruby_mod (starts with a lowercase letter; 2 to 64 lowercase letters, digits, or _) |
modName | The mod ID with each word capitalized | Ruby Mod |
modPackage | com.example.<mod ID without underscores> | io.github.you.ruby |
It changes, in place: poly.mod.json (ID, name, entrypoint), the entrypoint class (RubyMod) and its package folder, the resource folders (assets/my_mod/ → assets/ruby_mod/), the project name in settings.gradle.kts, the group and the log lines to check in build.gradle.kts, and the IntelliJ run configuration. It does not rename the folder itself; rename it yourself if you like. It runs only on an unchanged copy of the template, and if a renamed file would overwrite an existing one, it changes nothing.
Contributors with the Poly Mod Loader source, which is private for now, can also run newPolyMod with the same properties there. It copies the template into a new folder next to the source (or -PmodDir=<folder>) and renames it the same way.
Generate resource files: polyResources
Write the names of the blocks and items you registered in code into build.gradle.kts. The build then generates resource files in the same format as vanilla.
polyResources {
item("ruby") // flat item that uses textures/item/ruby.png
block("ruby_block") { minedWith = "pickaxe" } // cube block that uses textures/block/ruby_block.png
block("ruby_lamp") {
displayName = "Ruby Lamp"
texture = "minecraft:block/redstone_lamp_on"
dropsSelf = false
}
}
| Declaration | Generated files |
|---|---|
item("ruby") | assets/<mod>/items/ruby.json, assets/<mod>/models/item/ruby.json, and item.<mod>.ruby in lang/en_us.json |
block("ruby_block") | blockstates/ruby_block.json, models/block/ruby_block.json (cube_all), items/ruby_block.json, data/<mod>/loot_table/blocks/ruby_block.json (drops itself), and block.<mod>.ruby_block in lang/en_us.json |
minedWith = "pickaxe" | Adds the block to data/minecraft/tags/block/mineable/pickaxe.json ("replace": false) |
| Setting | Meaning | Default |
|---|---|---|
texture | Texture ID. Without a namespace, it is the mod's own (block/red → <mod>:block/red) | <mod>:item/<name>, <mod>:block/<name> |
displayName | English name | The name with each word capitalized (ruby_block → Ruby Block) |
minedWith (block) | pickaxe, axe, shovel, hoe | None |
dropsSelf (block) | Whether the block drops itself when broken | true |
Rules:
- Files you write by hand win. If
src/main/resourceshas a file at the same path, the tool does not generate that file. For a block with a different shape, such as stairs, you only need to write that one file yourself. lang/en_us.jsonand tool tags are merged. Entries you wrote stay as they are, values included, and only missing names are added. You write other language files, such as Korean, yourself.- It does not create texture PNGs. Draw them yourself and put them under
textures/. - Generated files are in
build/generated/poly-resources/mainand go into the jar. Nothing is written to the source folder.
Find mistakes before you start the game: checkPolyResources
build (check) validates all the resources that go into the jar (hand-written and generated), collects every problem, shows them, and then fails. The result is also saved in build/reports/poly/resource-problems.txt.
2 problems in the mod's resources (src/main/resources and polyResources):
POLY-RESOURCE-004 assets/ruby_mod/textures/item/Ruby.png: Minecraft only loads resource paths made of lowercase a-z, 0-9, _ . - and /, and skips this file; rename it to assets/ruby_mod/textures/item/ruby.png
POLY-RESOURCE-007 assets/ruby_mod/models/item/ruby.json: texture "item/ruby" has no namespace, so the game looks for minecraft:item/ruby; write "ruby_mod:item/ruby" for this mod's file
| Code | What it finds |
|---|---|
POLY-RESOURCE-004 | A file path the game skips (uppercase letters, spaces, and so on) |
POLY-RESOURCE-005 | JSON with a syntax error (trailing comma, missing quote). It gives the line and column |
POLY-RESOURCE-006 | A model file that an item definition, block state, or model parent points to does not exist |
POLY-RESOURCE-007 | A texture PNG that a model points to does not exist |
POLY-RESOURCE-008 | A translation file value is not a string |
POLY-RESOURCE-009 | A polyResources declaration error (invalid name, texture, or tool; the same name twice) |
Scope of the check: it verifies only references inside namespaces for which the mod has an assets/<namespace> folder. Files in minecraft: and in other mods are not here, so it does not check them. A reference written without a namespace (item/ruby) means minecraft:, so if the same path exists on the mod's side, the tool reports that you left out the namespace. References that depend on code registration, such as item IDs in recipes and loot, can be checked only in the game.
Next step
See code declarations and resources together in Make your first block.