Chapter 1, The Workshop
In which we point modern tools at 2011 and they just… work.
Every craft begins with a bench. Ours is the official ornithe-mod-template, the same starting point Ornithe recommends for any version, converted to target Beta 1.7.3 with biny mappings and RetroAPI. You can do the conversion by hand (this chapter shows every line), or skip it entirely:
⬇ bare-retroapi-template.zip , this chapter, already done
You need Java 21 to run Gradle and the game (the gen2 toolchain and the LWJGL3 runtime expect it). Your mod compiles for Java 21 too, modern language features on a 2011 game, courtesy of the modern JVM underneath.
The three files that matter
Starting from the stock template, exactly three files change: build.gradle (how to build), gradle.properties (which versions), and fabric.mod.json (who you are). Here is each one in its converted form.
build.gradle, Loom, Ploceus, and biny
The stock template uses Feather mappings on gen1 intermediary. We switch to gen2 intermediary and the community biny-ornithe mappings, and add the two mavens that host the b1.7.3 ecosystem:
plugins {
id 'java'
id 'net.fabricmc.fabric-loom-remap' version '1.16.3'
id 'ploceus' version '1.16.1'
// also builds a babric variant of your mod (build/libs/<name>-babric.jar)
id 'com.periut.retroconvert' version "${retroconvert_version}"
}
base {
archivesName = project.archives_base_name
}
version = "${project.version}+mc${project.minecraft_version}"
group = project.maven_group
ploceus {
setIntermediaryGeneration(2) // gen2, required for b1.7.3 + this ecosystem
}
repositories {
mavenLocal()
maven { url = 'https://matthewperiut.github.io/repository' } // gen2 mod deps (retroapi, retrocommands, starac)
maven { url = 'https://maven.glass-launcher.net/releases/' } // biny mappings
}
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// biny instead of Feather: human-readable names for the whole game
mappings ploceus.mappings("net.glasslauncher:biny-ornithe:b1.7.3+build.${project.biny_mappings}:mergedv2")
// exceptions/signatures/nests are per-side in beta (client and server were separate jars)
clientExceptions ploceus.raven(project.client_raven_build, 'client')
serverExceptions ploceus.raven(project.server_raven_build, 'server')
clientSignatures ploceus.sparrow(project.client_sparrow_build, 'client')
serverSignatures ploceus.sparrow(project.server_sparrow_build, 'server')
clientNests "net.glasslauncher:biny-nests:b1.7.3-client+build.${project.biny_nests_build}"
serverNests "net.glasslauncher:biny-nests:b1.7.3-server+build.${project.biny_nests_build}"
ploceus.dependOsl(project.osl_version) // entrypoints, networking, lifecycle events…
modImplementation "com.periut:retroapi:${project.retroapi_version}"
modImplementation("com.periut:retrocommands:${project.retrocommands_version}") {
exclude group: 'net.modificationstation'
exclude group: 'net.glasslauncher.mods'
exclude group: 'com.github.GeyserMC'
}
// starac brings LWJGL 3, which would clash with vanilla
// Minecraft's LWJGL 2 API, so keep it off the compile classpath.
modRuntimeOnly "com.periut:starac:${project.starac_version}"
}
// Exclude the Legacy Fabric LWJGL 2 wrapper at RUNTIME only (starac provides LWJGL 3).
// It must stay on the compile/minecraft classpath so Condor (Ploceus LVT generator)
// can resolve org.lwjgl.* classes referenced by b1.7.3 — a blanket exclude here
// strips LWJGL 2 from minecraftCompileLibraries and crashes LVT generation.
configurations.matching { it.name.toLowerCase().contains('runtime') }.configureEach {
exclude group: 'org.lwjgl.lwjgl'
}
processResources {
inputs.property 'version', version
filesMatching('fabric.mod.json') {
expand 'version': version
}
}
tasks.withType(JavaCompile).configureEach {
it.options.encoding = 'UTF-8'
it.options.release = 21
}
java {
// Still required by IDEs such as Eclipse and Visual Studio Code
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
withSourcesJar()
}
jar {
from('LICENSE') {
rename { "${it}_${base.archivesName.get()}" }
}
}Three guests came along with RetroAPI, all optional but very welcome in a dev environment:
| Dependency | What it does for you |
|---|---|
retroapi | The star of this guide, registration, persistence, networking, rendering. |
retrocommands | In-game commands (/give, /tp, …) while testing. Beta had almost none. |
starac | Runs the old client on LWJGL 3, modern keyboards, displays, and macOS support. Hence the LWJGL 2 exclusion just below it. |
gradle.properties, the version pinboard
# Gradle Properties
org.gradle.jvmargs = -Xmx1G
org.gradle.parallel = true
# Mod Properties
version = 1.0.0
maven_group = com.example # ← change me
archives_base_name = example_mod # ← change me
# Dependencies
retroapi_version=0.2.1
retrocommands_version = 0.7.4
starac_version=1.3.2
retroconvert_version = 1.0.1
# Ornithe Related Dependencies - check https://ornithemc.net/develop for the latest versions
minecraft_version = b1.7.3
loader_version = 0.19.3
biny_mappings = 9859f76
client_raven_build = 2
server_raven_build = 2
client_sparrow_build = 2
server_sparrow_build = 2
biny_nests_build = 2
osl_version = 0.18.0fabric.mod.json, your passport
Two lines change from the stock template, and one is added: the Minecraft version becomes beta (note the loader's spelling: 1.0.0-beta.7.3), and the mod now depends on RetroAPI so the loader refuses to launch without it, a crash at the door beats a crash in the basement:
{
"schemaVersion": 1,
"id": "example_mod",
"version": "${version}",
"name": "Example mod",
"description": "This is an example description! Tell everyone what your mod is about!",
"authors": [ "Me!" ],
"license": "CC0-1.0",
"icon": "assets/example_mod/icon.png",
"environment": "*",
"entrypoints": {
"init": [ "com.example.example_mod.ExampleMod" ]
},
"mixins": [ "example_mod.mixins.json" ],
"depends": {
"fabricloader": ">=0.17.3",
"minecraft": "1.0.0-beta.7.3",
"retroapi": ">=0.2.1",
"osl-entrypoints": ">=0.4.0"
}
}settings.gradle stays exactly as the template ships it, it already knows about the Fabric and Ornithe mavens that host the Gradle plugins.
Light the forge
That's the whole conversion. Prove it:
./gradlew runClientFirst run downloads the game, remaps it with biny, and decompile-links everything, give it a minute. Then Beta 1.7.3 opens with your mod loaded. Check the log for the line your ExampleMod.init() printed. To produce a shippable jar:
./gradlew build
# → build/libs/example_mod-1.0.0+mcb1.7.3.jarMake it yours
- Set
maven_groupandarchives_base_nameingradle.properties. - Set
id,name,description,authorsinfabric.mod.json, theidis load-bearing: it names your assets folder, your lang keys, and every identifier you register. - Rename the
com.example.example_modpackage andexample_mod.mixins.jsonto match.
The bench is built. Next: the three doors every mod walks through at launch.