Skip to content

Commit 365c0b7

Browse files
committed
Move everything to iroh
1 parent a9cbaa6 commit 365c0b7

156 files changed

Lines changed: 9154 additions & 2590 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ AutoModpack works by generating a modpack (**metadata file**) on the server, whi
4444

4545
When a client connects to the server:
4646

47-
1. Connection: AutoModpack establishes a secure connection and prompts you to [verify the server's certificate fingerprint](https://moddedmc.wiki/en/project/automodpack/docs/technicals/certificate).
47+
1. Connection: AutoModpack establishes an Iroh-based connection and prompts you to [verify the server's identity](https://moddedmc.wiki/en/project/automodpack/docs/technicals/certificate). The user-visible identity is the server's Iroh endpoint ID/public key.
4848
2. Direct links: Fetches the APIs for direct downloads of your modpack's files from Modrinth and CurseForge, where possible (mods, resource packs, shaders).
4949
3. Modpack download: All files are downloaded to the client's automodpack folder.
5050
4. Game restart: AutoModpack loads the modpack, and the client is perfectly synced and ready to play!

build.fabric.gradle.kts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
kotlin("jvm")
55
id("automodpack.common")
66
id("automodpack.utils")
7-
id("fabric-loom")
7+
id("net.fabricmc.fabric-loom-remap")
88
}
99

1010
version = "${property("mod_version")}"
@@ -42,7 +42,14 @@ dependencies {
4242

4343
// Required for translatable texts in 1.21.9+ for some reason i need both v0 and v1?
4444
if (sc.current.parsed >= "1.21.9") {
45-
include(modImplementation(fabricApi.module("fabric-resource-loader-v1", property("deps.fabric-api") as String))!!)
45+
include(
46+
modImplementation(
47+
fabricApi.module(
48+
"fabric-resource-loader-v1",
49+
property("deps.fabric-api") as String
50+
)
51+
)!!
52+
)
4653
}
4754
}
4855

buildSrc/src/main/kotlin/MergeJarTask.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ abstract class MergeJarTask : DefaultTask() {
3434
@get:OutputFile
3535
abstract val outputJar: RegularFileProperty
3636

37+
private fun resolveSingleOptionalJar(libsDir: File, prefix: String): File? {
38+
val matches = libsDir.listFiles()
39+
?.filter { file -> file.isFile && file.name.startsWith(prefix) && file.name.endsWith(".jar") }
40+
?.sortedBy { it.name }
41+
.orEmpty()
42+
43+
return when (matches.size) {
44+
0 -> null
45+
1 -> matches.single()
46+
else -> error(
47+
"Expected at most one ${prefix}*.jar in ${libsDir.absolutePath}, " +
48+
"but found ${matches.size}: ${matches.joinToString { it.name }}"
49+
)
50+
}
51+
}
52+
3753
@TaskAction
3854
fun mergeJars() {
3955
val mergedDir = File(mergedDirPath.get())
@@ -56,7 +72,6 @@ abstract class MergeJarTask : DefaultTask() {
5672
val zstdFile = libsDir.listFiles()
5773
?.firstOrNull { file -> file.isFile && file.name.startsWith("zstd-jni-") && file.name.endsWith(".jar") }
5874
?: error("No zstd-jni-*.jar found in libs directory! ${libsDir.absolutePath}")
59-
6075
val finalJar = File(mergedDir, jarToMerge.name)
6176

6277
val seen = mutableSetOf<String>()
@@ -84,6 +99,6 @@ abstract class MergeJarTask : DefaultTask() {
8499
}
85100

86101
outputJar.get().asFile.writeText(finalJar.absolutePath)
87-
println("Merged: ${jarToMerge.name} and ${zstdFile.name} from: ${loaderFile.name} into: ${finalJar.name} Took: ${System.currentTimeMillis() - time}ms")
102+
println("Merged: ${jarToMerge.name}, ${zstdFile.name} from: ${loaderFile.name} into: ${finalJar.name} Took: ${System.currentTimeMillis() - time}ms")
88103
}
89-
}
104+
}

buildSrc/src/main/kotlin/automodpack.common.gradle.kts

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import java.security.MessageDigest
22
import java.math.BigInteger
3+
import org.gradle.api.plugins.BasePluginExtension
34

45
plugins {
56
idea
@@ -17,6 +18,11 @@ repositories {
1718
maven("https://maven.fabricmc.net/")
1819
}
1920

21+
tasks.register("prepareKotlinBuildScriptModel") {
22+
// IntelliJ may request this task against individual Stonecutter variant projects.
23+
// The real model task exists on the root build; leaf projects only need a no-op.
24+
}
25+
2026
tasks.named("build") {
2127
val taksToRun = mutableListOf<String>()
2228
for (module in getAllDependentLoaderModules(project.name)) {
@@ -26,36 +32,50 @@ tasks.named("build") {
2632
finalizedBy(tasks.named("mergeJar"))
2733
}
2834

29-
val mergedDirPath = rootProject.projectDir.absolutePath + "/merged"
35+
val mergedRootDir = rootProject.projectDir.resolve("merged")
36+
val projectMergedStagingDir = mergedRootDir.resolve(".staging").resolve(project.name)
37+
val publishedMergedJarFileName = providers.provider {
38+
val baseExtension = extensions.getByType<BasePluginExtension>()
39+
"${baseExtension.archivesName.get()}-${project.version}.jar"
40+
}
41+
val publishedMergedJarPath = publishedMergedJarFileName.map { mergedRootDir.resolve(it).absolutePath }
3042

3143
tasks.named("clean") {
3244
finalizedBy("cleanMerged")
3345
}
3446

3547
tasks.register("cleanMerged") {
36-
val mergedDir = mergedDirPath
48+
val mergedDir = projectMergedStagingDir
3749
doLast {
38-
File(mergedDir).deleteRecursively()
50+
mergedDir.deleteRecursively()
51+
File(publishedMergedJarPath.get()).delete()
3952
}
4053
}
4154

4255
val mergeJarTask = tasks.register<MergeJarTask>("mergeJar") {
43-
this.mergedDirPath.set(project.rootProject.projectDir.absolutePath + "/merged")
56+
this.mergedDirPath.set(projectMergedStagingDir.absolutePath)
4457
this.rootProjectPath.set(project.rootProject.projectDir.absolutePath)
4558
this.libsPath.set(project.rootProject.projectDir.absolutePath + "/libs")
4659
this.buildDirectory.set(layout.buildDirectory)
4760
this.outputJar.set(layout.buildDirectory.file("merged-jar-path.txt"))
4861

4962
val filesToHash = mutableListOf<Any>()
5063
for (module in getAllDependentLoaderModules(project.name)) {
51-
val modLoaderJar = rootProject.project(module).tasks.named("jar")
52-
filesToHash.add(modLoaderJar)
64+
val moduleBuildDir = rootProject.project(module).layout.buildDirectory
65+
filesToHash.add(fileTree(moduleBuildDir) {
66+
include("libs/*.jar")
67+
exclude("libs/*-sources.jar")
68+
})
5369
}
70+
filesToHash.add(fileTree(rootProject.projectDir.resolve("libs")) {
71+
include("zstd-jni-*.jar")
72+
include("iroh-pipes-jni-*.jar")
73+
})
5474

5575
// Compute the actual hash of the content of all input jars.
5676
// We use a provider so this is calculated just before task execution, ensuring files exist.
5777
this.inputHash.set(provider {
58-
val outputFile = File(mergedDirPath.get(), getMergedJarPath(buildDirectory.get().dir("libs").asFile).name)
78+
val outputFile = File(this@register.mergedDirPath.get(), getMergedJarPath(buildDirectory.get().dir("libs").asFile).name)
5979
if (!outputFile.exists()) { // Return a random hash if the output file doesn't exist yet. We need to have something.
6080
return@provider BigInteger(1, MessageDigest.getInstance("MD5").digest(System.currentTimeMillis().toString().toByteArray())).toString(16)
6181
}
@@ -83,7 +103,8 @@ val mergeJarTask = tasks.register<MergeJarTask>("mergeJar") {
83103
val mergedJarWrapper = tasks.register<Jar>("mergedJarWrapper") {
84104
dependsOn(mergeJarTask)
85105
enabled = false
86-
destinationDirectory.set(File(mergedDirPath))
106+
destinationDirectory.set(projectMergedStagingDir)
107+
archiveFileName.set(publishedMergedJarFileName)
87108
}
88109

89110
val optimizedMergedJar = jarOptimizer.register(mergedJarWrapper, "pl.skidam", "amp_libs.org.bouncycastle.jcajce.provider.asymmetric")
@@ -93,6 +114,7 @@ tasks.register("optimizeMergedJar") {
93114

94115
val outputJarFile = mergeJarTask.flatMap { it.outputJar }
95116
val optimizedFileProvider = optimizedMergedJar.flatMap { it.archiveFile }
117+
val publishedJarPathProvider = publishedMergedJarPath
96118

97119
inputs.file(outputJarFile)
98120

@@ -110,7 +132,11 @@ tasks.register("optimizeMergedJar") {
110132
if (optimizedFile.exists() && optimizedFile.length() > 0) {
111133
jarFile.delete()
112134
optimizedFile.renameTo(jarFile)
113-
println("Optimized ${jarFile.name} - Took: ${System.currentTimeMillis() - time}ms")
114135
}
136+
137+
mergedRootDir.mkdirs()
138+
val publishedJar = File(publishedJarPathProvider.get())
139+
jarFile.copyTo(publishedJar, overwrite = true)
140+
println("Optimized ${jarFile.name} - Took: ${System.currentTimeMillis() - time}ms")
115141
}
116-
}
142+
}
Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
tasks.named<ProcessResources>("processResources") {
2+
val isIdeaSync = System.getProperty("idea.sync.active", "false").toBoolean()
3+
24
fun prop(name: String) = project.findProperty(name) as? String
35

46
val props = HashMap<String, String>().apply {
57
fun putIfNotEmpty(key: String, value: String?) {
68
if (!value.isNullOrEmpty()) put(key, value)
79
}
810

9-
putIfNotEmpty("version",prop("mod_version"))
10-
putIfNotEmpty("minecraft",prop("meta.minecraft"))
11-
putIfNotEmpty("id",prop("mod.id"))
12-
putIfNotEmpty("name",prop("mod_name"))
13-
putIfNotEmpty("description",prop("mod.description"))
11+
putIfNotEmpty("version", prop("mod_version"))
12+
putIfNotEmpty("minecraft", prop("meta.minecraft"))
13+
putIfNotEmpty("id", prop("mod.id"))
14+
putIfNotEmpty("name", prop("mod_name"))
15+
putIfNotEmpty("description", prop("mod.description"))
1416
}
1517

16-
filesMatching(listOf("pack.mcmeta", "fabric.mod.json", "META-INF/neoforge.mods.toml", "META-INF/mods.toml")) {
17-
expand(props)
18+
inputs.properties(props)
19+
20+
if (!isIdeaSync) { // dont match on idea sync - fixes bunch of warnings
21+
filesMatching(listOf("pack.mcmeta", "fabric.mod.json", "META-INF/neoforge.mods.toml", "META-INF/mods.toml")) {
22+
expand(props)
23+
}
1824
}
19-
}
25+
}

core/build.gradle.kts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
import java.io.File
23

34
plugins {
45
kotlin("jvm")
@@ -19,17 +20,45 @@ val deps = listOf(
1920
"io.netty:netty-all:4.2.9.Final",
2021
"org.apache.logging.log4j:log4j-core:2.25.2",
2122
"com.google.code.gson:gson:2.13.2",
22-
"org.bouncycastle:bcpkix-jdk18on:1.82",
2323
"org.apache.httpcomponents.client5:httpclient5:5.5.1",
2424
"org.tomlj:tomlj:1.1.1",
25-
"com.h2database:h2-mvstore:2.4.240"
25+
"com.h2database:h2-mvstore:2.4.240",
26+
"dnsjava:dnsjava:3.6.4"
2627
)
2728

29+
fun resolveSingleIrohPipesJniJar(): File {
30+
val libsDir = rootProject.projectDir.resolve("libs")
31+
val matches = libsDir.listFiles()
32+
?.filter { file -> file.isFile && file.name.startsWith("iroh-pipes-jni-") && file.name.endsWith(".jar") }
33+
?.sortedBy { it.name }
34+
.orEmpty()
35+
36+
return when (matches.size) {
37+
1 -> matches.single()
38+
0 -> error(
39+
"Missing automodpack/libs/iroh-pipes-jni-*.jar. " +
40+
"Run scripts/update-iroh-jni.sh from the repository root before building AutoModpack."
41+
)
42+
else -> error(
43+
"Expected exactly one automodpack/libs/iroh-pipes-jni-*.jar but found ${matches.size}: " +
44+
matches.joinToString { it.name }
45+
)
46+
}
47+
}
48+
49+
val irohPipesJniJar = files(resolveSingleIrohPipesJniJar())
50+
val stagedIrohNativesDir = rootProject.projectDir.resolve("libs/.iroh-staging")
51+
val unpackedIrohJavaDir = layout.buildDirectory.dir("generated/iroh-pipes-jni-java")
52+
2853
dependencies {
2954
// minecraft/loaders uses these, so we cant just implement them because it wont resolve in gradle
3055
deps.forEach { compileOnly(it) }
3156
deps.forEach { runtimeOnly(it) }
3257
deps.forEach { testImplementation(it) }
58+
compileOnly("org.slf4j:slf4j-api:1.7.36")
59+
testImplementation("org.slf4j:slf4j-api:1.7.36")
60+
compileOnly(irohPipesJniJar)
61+
testImplementation(irohPipesJniJar)
3362

3463
testImplementation("org.junit.jupiter:junit-jupiter:6.0.1")
3564
testRuntimeOnly("org.junit.platform:junit-platform-launcher:6.0.1")
@@ -47,6 +76,28 @@ tasks.withType<JavaCompile> {
4776
options.encoding = "UTF-8"
4877
}
4978

79+
val unpackIrohPipesJniJava by tasks.registering(Sync::class) {
80+
from({
81+
zipTree(resolveSingleIrohPipesJniJar())
82+
}) {
83+
include("dev/iroh/**")
84+
exclude("META-INF/natives/**")
85+
exclude("META-INF/MANIFEST.MF")
86+
exclude("META-INF/*.SF")
87+
exclude("META-INF/*.DSA")
88+
exclude("META-INF/*.RSA")
89+
}
90+
into(unpackedIrohJavaDir)
91+
}
92+
93+
tasks.named<ProcessResources>("processResources") {
94+
dependsOn(unpackIrohPipesJniJava)
95+
from(stagedIrohNativesDir) {
96+
into("META-INF/natives/iroh")
97+
}
98+
from(unpackedIrohJavaDir)
99+
}
100+
50101
tasks.named<Test>("test") {
51102
useJUnitPlatform()
52103
}
@@ -65,4 +116,4 @@ tasks.named<ShadowJar>("shadowJar") {
65116

66117
tasks.named("assemble") {
67118
dependsOn("shadowJar")
68-
}
119+
}

0 commit comments

Comments
 (0)