Scaffold the emote library with a Stonecutter Fabric mod and tester

- core/: Minecraft-independent animation model (Bone, BoneTransform with
  bend fields, Pose, Animation, AnimationPlayer) with JUnit tests.
- src/main: Fabric mod built for 1.21.4-1.21.11 with Stonecutter on
  Mojang mappings. Samples each player's pose into its render state and
  applies it at the end of HumanoidModel.setupAnim (armor follows too).
- src/testmod: dev-only tester with /emotes play|stop|info and a mixin
  audit on startup.
- Publishing to the saturnclientmc Gitea Maven registry as
  org.saturnclient:emotes-core and emotes-fabric:<v>+<mc>.

Loom is pinned to 1.17 because 1.18 needs a Java 25 JVM.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-09-26 19:05:06 +02:00
co-authored by claude
parent dda96c4acf
commit 8641fc0afe
31 changed files with 1303 additions and 22 deletions
+115
View File
@@ -0,0 +1,115 @@
// Build script for each Minecraft version node (versions/<mc>/). The root project itself
// is configured by stonecutter.gradle.kts.
plugins {
// Applies the right Loom variant for the node's Minecraft version.
id("dev.kikugie.loom-back-compat")
`maven-publish`
}
// DO NOT set group = ...! (Stonecutter/loom-back-compat reads mod.group.)
val modVersion = property("mod.version") as String
version = "$modVersion+${sc.current.version}"
base.archivesName = "emotes-fabric"
val requiredJava: JavaVersion = when {
sc.current.parsed >= "26.1" -> JavaVersion.VERSION_25
else -> JavaVersion.VERSION_21
}
val testmod: SourceSet = sourceSets.create("testmod") {
compileClasspath += sourceSets.main.get().compileClasspath + sourceSets.main.get().output
runtimeClasspath += sourceSets.main.get().runtimeClasspath + sourceSets.main.get().output
}
loom {
createRemapConfigurations(testmod)
mods {
register("saturn_emotes") { sourceSet(sourceSets.main.get()) }
register("saturn_emotes_testmod") { sourceSet(testmod) }
}
decompilerOptions.named("vineflower") {
options.put("mark-corresponding-synthetics", "1") // Names lambdas, useful for mixins
}
runs {
// ./gradlew :<mc>:runTestmodClient launches the game with the tester mod loaded.
register("testmodClient") {
client()
name = "Testmod Client"
source(testmod)
}
}
runConfigs.all {
preferGradleTask = true
generateRunConfig = true
runDirectory = rootProject.file("run") // Shared by every version
jvmArguments.add("-Dmixin.debug.export=true")
}
}
dependencies {
fun fapi(vararg modules: String) {
for (it in modules) modImplementation(fabricApi.module(it, sc.properties["deps.fabric_api"]))
}
minecraft("com.mojang:minecraft:${sc.current.version}")
loomx.applyMojangMappings()
modImplementation("net.fabricmc:fabric-loader:${property("deps.fabric_loader")}")
fapi("fabric-api-base", "fabric-lifecycle-events-v1")
// The core is Minecraft-independent; ship it inside the mod jar.
api(project(":core"))
include(project(":core"))
"modTestmodImplementation"(fabricApi.module("fabric-command-api-v2", sc.properties["deps.fabric_api"]))
}
java {
withSourcesJar()
targetCompatibility = requiredJava
sourceCompatibility = requiredJava
toolchain.languageVersion = JavaLanguageVersion.of(requiredJava.majorVersion)
}
tasks {
val props = mapOf(
"id" to sc.properties["mod.id"],
"name" to sc.properties["mod.name"],
"version" to version.toString(),
"minecraft" to sc.properties["mod.mc_compat"],
"loader" to Regex("\\d+\\.\\d+").find(sc.properties.get<String>("deps.fabric_loader"))!!.value,
"java" to "JAVA_${requiredJava.majorVersion}",
)
withType<ProcessResources>().configureEach {
inputs.properties(props)
filesMatching(listOf("fabric.mod.json", "*.mixins.json")) { expand(props) }
}
withType<Jar>().configureEach {
from(rootProject.file("LICENSE")) { rename { "${it}_saturn_emotes" } }
}
register<Copy>("buildAndCollect") {
group = "build"
description = "Builds the mod jar and copies it to build/libs/<mod version>/ in the root project"
from(loomx.modJar.flatMap { it.archiveFile })
into(rootProject.layout.buildDirectory.dir("libs/$modVersion"))
}
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = property("mod.group") as String
artifactId = "emotes-fabric"
from(components["java"])
}
}
}
apply(from = rootProject.file("gradle/gitea.gradle.kts"))