automatically download assets

- format
This commit is contained in:
moehreag 2024-07-02 21:21:04 +02:00
parent 47b6d93b18
commit 3c1ddb496e
9 changed files with 54 additions and 65 deletions

View file

@ -63,8 +63,12 @@ class PhytotelmaPlugin : Plugin<Project> {
c.isCanBeConsumed = false c.isCanBeConsumed = false
when (conf.dependencyType) { when (conf.dependencyType) {
DependencyType.RUNTIME -> project.configurations.getByName(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME).extendsFrom(c) DependencyType.RUNTIME -> project.configurations.getByName(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME)
DependencyType.COMPILE -> project.configurations.getByName(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME).extendsFrom(c) .extendsFrom(c)
DependencyType.COMPILE -> project.configurations.getByName(JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME)
.extendsFrom(c)
DependencyType.NONE -> {} DependencyType.NONE -> {}
} }
} }
@ -88,31 +92,5 @@ class PhytotelmaPlugin : Plugin<Project> {
companion object { companion object {
lateinit var globalCacheDir: Path lateinit var globalCacheDir: Path
val remappedConfigurationNames = mapOf(
JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME to listOf(
JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME
),
JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME to listOf(
JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME
),
JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME to listOf(
JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME
),
JavaPlugin.TEST_COMPILE_ONLY_CONFIGURATION_NAME to listOf(
JavaPlugin.TEST_COMPILE_CLASSPATH_CONFIGURATION_NAME
),
JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME to listOf(
JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME,
JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME,
),
JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME to listOf(
JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME,
)
)
} }
} }

View file

@ -1,3 +1,5 @@
@file:Suppress("unused")
package dev.frogmc.phytotelma package dev.frogmc.phytotelma
import com.google.gson.Gson import com.google.gson.Gson
@ -5,9 +7,11 @@ import com.google.gson.GsonBuilder
import dev.frogmc.phytotelma.common.CachingHttpClient import dev.frogmc.phytotelma.common.CachingHttpClient
import org.gradle.api.Project import org.gradle.api.Project
import java.net.URI import java.net.URI
import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.* import kotlin.io.path.createDirectories
import kotlin.io.path.exists
import kotlin.io.path.writeBytes
import kotlin.io.path.writeText
object VersionChecker { object VersionChecker {
private var validVersions = mutableListOf<VersionUrl>() private var validVersions = mutableListOf<VersionUrl>()
@ -77,17 +81,6 @@ object VersionChecker {
return fetchVersionData(version).downloads.client return fetchVersionData(version).downloads.client
} }
fun downloadAssetIndex(version: String, path: Path): String {
val index = fetchVersionData(version).assetIndex
val dest = path.resolve(index.id + ".json")
if (dest.notExists()) {
CachingHttpClient.getUncached(URI.create(index.url)).use {
Files.copy(it, dest)
}
}
return index.id
}
private fun rawDownload(url: String): ByteArray { private fun rawDownload(url: String): ByteArray {
return CachingHttpClient.getUncached(URI.create(url)).readAllBytes() return CachingHttpClient.getUncached(URI.create(url)).readAllBytes()
} }

View file

@ -177,14 +177,14 @@ abstract class MinecraftConfiguration @Inject constructor(
var back = MappingBundle() var back = MappingBundle()
var name = "layer[" var name = "layer["
val layers = conf.layers.mapIndexed {index, provider -> val layers = conf.layers.mapIndexed { index, provider ->
val bundle = provider.get().flatten(true) val bundle = provider.get().flatten(true)
if (index == 0) { if (index == 0) {
name+=mappingsName name += mappingsName
back.insert(bundle) back.insert(bundle)
return@mapIndexed bundle return@mapIndexed bundle
} }
name+=", $mappingsName" name += ", $mappingsName"
back = back.flatten(false) back = back.flatten(false)
val prevDst = back.data[0].dstNamespace val prevDst = back.data[0].dstNamespace

View file

@ -27,6 +27,7 @@ import org.jetbrains.java.decompiler.main.Fernflower
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger
import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver import org.jetbrains.java.decompiler.main.decompiler.SingleFileSaver
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences
import java.io.OutputStream
import java.io.PrintStream import java.io.PrintStream
import java.nio.file.FileSystems import java.nio.file.FileSystems
import java.nio.file.Files import java.nio.file.Files
@ -99,7 +100,7 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
project.tasks.register(Constants.DOWNLOAD_ASSETS_TASK) { task -> project.tasks.register(Constants.DOWNLOAD_ASSETS_TASK) { task ->
task.group = Constants.TASK_GROUP task.group = Constants.TASK_GROUP
task.doFirst { task.doFirst {
AssetDownloader.download(it.project) AssetDownloader.download(it.project, true)
} }
} }
@ -190,6 +191,9 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
} }
private fun remapModDependencies() { private fun remapModDependencies() {
val out = System.out
// Mute the output from thyroxine as there may be a lot of remapping operations here
System.setOut(PrintStream(OutputStream.nullOutputStream()))
ModConfigurations.configurations.forEach { conf -> ModConfigurations.configurations.forEach { conf ->
val artifacts = project.configurations.getByName("mod" + conf.name.capitalized()) val artifacts = project.configurations.getByName("mod" + conf.name.capitalized())
.resolvedConfiguration.resolvedArtifacts .resolvedConfiguration.resolvedArtifacts
@ -244,12 +248,11 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
) )
} }
} }
System.setOut(out)
} }
override fun minecraft(action: Action<MinecraftConfiguration>) { override fun minecraft(action: Action<MinecraftConfiguration>) {
println("Setting up Tasks...")
setupTasks() setupTasks()
println("Setting up Minecraft...")
val mcConf = objects.newInstance(MinecraftConfiguration::class.java) val mcConf = objects.newInstance(MinecraftConfiguration::class.java)
action.execute(mcConf) action.execute(mcConf)
@ -272,7 +275,6 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
projectData.localCacheDir!!.resolve("net/minecraft/client/$version/client-$version-remapped.jar") projectData.localCacheDir!!.resolve("net/minecraft/client/$version/client-$version-remapped.jar")
remappedJar.createParentDirectories() remappedJar.createParentDirectories()
projectData.remappedGameJarPath = remappedJar projectData.remappedGameJarPath = remappedJar
println("Time to setup Minecraft!")
val applyAW = AccessWidener.needsUpdate(project) val applyAW = AccessWidener.needsUpdate(project)
if (remappedJar.notExists() || applyAW || mcConf.mappingsName != projectData.mappingsName) { if (remappedJar.notExists() || applyAW || mcConf.mappingsName != projectData.mappingsName) {
projectData.mappingsName = mcConf.mappingsName projectData.mappingsName = mcConf.mappingsName
@ -294,8 +296,8 @@ abstract class PhytotelmaGradleExtensionImpl @Inject constructor(
VersionChecker.savePomFile(version, remappedJar.parent) VersionChecker.savePomFile(version, remappedJar.parent)
project.dependencies.add(Constants.MINECRAFT_CONFIGURATION, "net.minecraft:client:$version:remapped") project.dependencies.add(Constants.MINECRAFT_CONFIGURATION, "net.minecraft:client:$version:remapped")
println("Generating run configurations...")
RunConfigGenerator.generate(project) RunConfigGenerator.generate(project)
AssetDownloader.download(project)
if (applyAW) { if (applyAW) {
project.afterEvaluate { project.afterEvaluate {

View file

@ -35,7 +35,7 @@ fun MappingBundle.filterClasses(filter: (String) -> Boolean): MappingBundle {
newData.parameters.putAll(parameters.filter { newData.classes.containsKey(it.key.owner) }) newData.parameters.putAll(parameters.filter { newData.classes.containsKey(it.key.owner) })
} }
val bundle = MappingBundle(data.subList(0, data.size-1).plus(newData), mutableListOf()) val bundle = MappingBundle(data.subList(0, data.size - 1).plus(newData), mutableListOf())
if (oldDocs != null) { if (oldDocs != null) {
val newDocs = DocumentationData(newData.dstNamespace) val newDocs = DocumentationData(newData.dstNamespace)

View file

@ -110,8 +110,8 @@ object Nester {
val matcher = pattern.matcher(version) val matcher = pattern.matcher(version)
matcher.find() matcher.find()
val semver = matcher.group(1) + val semver = matcher.group(1) +
(if (matcher.group(2) != null) "-"+matcher.group(2) else "") + (if (matcher.group(2) != null) "-" + matcher.group(2) else "") +
(if (matcher.group(3) != null) "+"+matcher.group(3) else "") (if (matcher.group(3) != null) "+" + matcher.group(3) else "")
it.getPath("frog.mod.toml").writeText( it.getPath("frog.mod.toml").writeText(
""" """
[frog] [frog]

View file

@ -9,43 +9,59 @@ import dev.frogmc.phytotelma.common.CachingHttpClient
import org.gradle.api.Project import org.gradle.api.Project
import java.net.URI import java.net.URI
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.notExists
import kotlin.io.path.reader import kotlin.io.path.reader
object AssetDownloader { object AssetDownloader {
private const val ASSETS_URL = "https://resources.download.minecraft.net" private const val ASSETS_URL = "https://resources.download.minecraft.net"
fun download(project: Project) { fun download(project: Project, manualInvocation: Boolean = false) {
val version = ProjectStorage.get(project).minecraftVersion!! val version = ProjectStorage.get(project).minecraftVersion!!
val path = PhytotelmaPlugin.globalCacheDir.resolve("assets") val path = PhytotelmaPlugin.globalCacheDir.resolve("assets")
val id = VersionChecker.downloadAssetIndex(version, path.resolve("indexes")) val assetIndex = VersionChecker.fetchVersionData(version).assetIndex
val dest = path.resolve("indexes").resolve(assetIndex.id + ".json")
var overwrite = manualInvocation
if (dest.notExists()) {
CachingHttpClient.getUncached(URI.create(assetIndex.url)).use {
Files.copy(it, dest)
}
overwrite = true
}
val index = Gson().fromJson( val index = Gson().fromJson(
path.resolve("indexes").resolve("$id.json").reader(StandardCharsets.UTF_8), path.resolve("indexes").resolve("${assetIndex.id}.json").reader(StandardCharsets.UTF_8),
JsonObject::class.java JsonObject::class.java
) )
val objectsPath = path.resolve("objects") val objectsPath = path.resolve("objects")
objectsPath.createDirectories() objectsPath.createDirectories()
val entries = index.getAsJsonObject("objects").entrySet() val entries = index.getAsJsonObject("objects").entrySet()
val totalSize = entries.size val totalSize = entries.size
if (overwrite) {
print("Downloading $totalSize assets... ()") print("Downloading $totalSize assets... ()")
System.out.flush() System.out.flush()
}
entries.forEachIndexed { i, it -> entries.forEachIndexed { i, it ->
val hash = it.value.asJsonObject.get("hash").asString val hash = it.value.asJsonObject.get("hash").asString
/*val size = it.value.asJsonObject.get("size").asInt /*val size = it.value.asJsonObject.get("size").asInt
val name = it.key*/ val name = it.key*/
// TODO asset downloading for versions <=1.7 (legacy) // TODO asset downloading for versions <=1.7 (legacy)
print("\rDownloading $totalSize assets... ($i/$totalSize): $hash"+" ".repeat(30)) if (overwrite) {
print("\rDownloading $totalSize assets... ($i/$totalSize): $hash" + " ".repeat(30))
System.out.flush() System.out.flush()
get(objectsPath, hash)
} }
println("\rDownloading $totalSize assets... Done!"+" ".repeat(50)) get(objectsPath, hash, overwrite)
}
if (overwrite) {
println("\rDownloading $totalSize assets... Done!" + " ".repeat(50))
}
} }
private fun get(localDir: Path, hash: String) { private fun get(localDir: Path, hash: String, overwrite: Boolean) {
val shortHash = hash.substring(0, 2) val shortHash = hash.substring(0, 2)
val path = localDir.resolve("$shortHash/$hash") val path = localDir.resolve("$shortHash/$hash")
CachingHttpClient.downloadTo(URI.create("$ASSETS_URL/$shortHash/$hash"), path, true) CachingHttpClient.downloadTo(URI.create("$ASSETS_URL/$shortHash/$hash"), path, overwrite)
} }
} }

View file

@ -34,7 +34,7 @@ object RunConfigGenerator {
assetIndexPath.createDirectories() assetIndexPath.createDirectories()
} }
val projectData = ProjectStorage.get(project) val projectData = ProjectStorage.get(project)
val indexId = VersionChecker.downloadAssetIndex(projectData.minecraftVersion!!, assetIndexPath) val indexId = VersionChecker.fetchVersionData(projectData.minecraftVersion!!).assetIndex.id
val projectName = if (project.rootDir == project.projectDir) "" else " (${project.name})" val projectName = if (project.rootDir == project.projectDir) "" else " (${project.name})"

View file

@ -29,7 +29,7 @@ abstract class RunGameTask @Inject constructor(env: Env) : JavaExec() {
if (assetIndexPath.notExists()) { if (assetIndexPath.notExists()) {
assetIndexPath.createDirectories() assetIndexPath.createDirectories()
} }
val indexId = VersionChecker.downloadAssetIndex(ProjectStorage.get(project).minecraftVersion!!, assetIndexPath) val indexId = VersionChecker.fetchVersionData(ProjectStorage.get(project).minecraftVersion!!).assetIndex.id
val log4jPath = project.rootDir.resolve(".gradle/phytotelma/log4j.xml").toPath().absolute() val log4jPath = project.rootDir.resolve(".gradle/phytotelma/log4j.xml").toPath().absolute()
if (log4jPath.notExists()) { if (log4jPath.notExists()) {
log4jPath.createParentDirectories() log4jPath.createParentDirectories()